List:Commits« Previous MessageNext Message »
From:Alex Ivanov Notebook Date:March 3 2006 8:34pm
Subject:bk commit into 5.1 tree (aivanov:1.2214)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 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.2214 06/03/03 22:34:24 aivanov@stripped +39 -0
  Applying innodb-5.1-ss160 snapshot
    Intermediate, not to be pushed

  mysql-test/t/innodb_unsafe_binlog.test
    1.1 06/03/03 22:34:17 aivanov@stripped +55 -0
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  mysql-test/t/innodb_unsafe_binlog-master.opt
    1.1 06/03/03 22:34:17 aivanov@stripped +1 -0
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  mysql-test/r/innodb_unsafe_binlog.result
    1.1 06/03/03 22:34:17 aivanov@stripped +35 -0
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/trx/trx0trx.c
    1.63 06/03/03 22:34:17 aivanov@stripped +2 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/sync/sync0sync.c
    1.38 06/03/03 22:34:17 aivanov@stripped +1 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/sync/sync0arr.c
    1.22 06/03/03 22:34:17 aivanov@stripped +188 -97
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  mysql-test/t/innodb_unsafe_binlog.test
    1.0 06/03/03 22:34:17 aivanov@stripped +0 -0
    BitKeeper file
/home/alexi/innodb/mysql-5.1-xx160/mysql-test/t/innodb_unsafe_binlog.test

  mysql-test/t/innodb_unsafe_binlog-master.opt
    1.0 06/03/03 22:34:17 aivanov@stripped +0 -0
    BitKeeper file
/home/alexi/innodb/mysql-5.1-xx160/mysql-test/t/innodb_unsafe_binlog-master.opt

  mysql-test/r/innodb_unsafe_binlog.result
    1.0 06/03/03 22:34:17 aivanov@stripped +0 -0
    BitKeeper file
/home/alexi/innodb/mysql-5.1-xx160/mysql-test/r/innodb_unsafe_binlog.result

  storage/innobase/srv/srv0start.c
    1.91 06/03/03 22:34:16 aivanov@stripped +40 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/srv/srv0srv.c
    1.97 06/03/03 22:34:16 aivanov@stripped +18 -5
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/row/row0sel.c
    1.101 06/03/03 22:34:16 aivanov@stripped +4 -3
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/row/row0mysql.c
    1.122 06/03/03 22:34:16 aivanov@stripped +28 -41
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/row/row0ins.c
    1.77 06/03/03 22:34:16 aivanov@stripped +22 -27
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/rem/rem0cmp.c
    1.32 06/03/03 22:34:16 aivanov@stripped +6 -5
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/os/os0thread.c
    1.33 06/03/03 22:34:16 aivanov@stripped +0 -9
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/os/os0sync.c
    1.29 06/03/03 22:34:16 aivanov@stripped +15 -15
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/os/os0file.c
    1.114 06/03/03 22:34:16 aivanov@stripped +72 -40
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/lock/lock0lock.c
    1.66 06/03/03 22:34:16 aivanov@stripped +11 -8
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/univ.i
    1.47 06/03/03 22:34:16 aivanov@stripped +9 -0
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/sync0arr.h
    1.9 06/03/03 22:34:16 aivanov@stripped +5 -5
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/srv0srv.h
    1.60 06/03/03 22:34:16 aivanov@stripped +13 -2
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/row0mysql.h
    1.47 06/03/03 22:34:16 aivanov@stripped +0 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/rem0cmp.h
    1.12 06/03/03 22:34:15 aivanov@stripped +2 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/os0file.h
    1.45 06/03/03 22:34:15 aivanov@stripped +4 -3
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/dict0load.h
    1.12 06/03/03 22:34:15 aivanov@stripped +2 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/dict0dict.h
    1.41 06/03/03 22:34:15 aivanov@stripped +2 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/db0err.h
    1.13 06/03/03 22:34:15 aivanov@stripped +0 -4
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/data0type.ic
    1.29 06/03/03 22:34:15 aivanov@stripped +24 -15
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/data0type.h
    1.24 06/03/03 22:34:15 aivanov@stripped +2 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/buf0buf.h
    1.34 06/03/03 22:34:15 aivanov@stripped +9 -3
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/include/btr0sea.ic
    1.5 06/03/03 22:34:15 aivanov@stripped +1 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/fil/fil0fil.c
    1.62 06/03/03 22:34:15 aivanov@stripped +81 -2
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/dict/dict0load.c
    1.45 06/03/03 22:34:15 aivanov@stripped +20 -9
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/dict/dict0dict.c
    1.76 06/03/03 22:34:15 aivanov@stripped +15 -22
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  storage/innobase/btr/btr0sea.c
    1.39 06/03/03 22:34:15 aivanov@stripped +51 -24
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  sql/ha_innodb.h
    1.118 06/03/03 22:34:15 aivanov@stripped +2 -13
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  sql/ha_innodb.cc
    1.259 06/03/03 22:34:15 aivanov@stripped +188 -159
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  mysql-test/t/innodb_cache.test
    1.13 06/03/03 22:34:15 aivanov@stripped +0 -4
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  mysql-test/t/innodb.test
    1.131 06/03/03 22:34:14 aivanov@stripped +382 -20
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  mysql-test/r/innodb_cache.result
    1.14 06/03/03 22:34:14 aivanov@stripped +1 -1
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

  mysql-test/r/innodb.result
    1.164 06/03/03 22:34:14 aivanov@stripped +481 -44
    Applying innodb-5.1-ss160 snapshot
      Intermediate, not to be pushed

# 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.1-xx160
--- New file ---
+++ mysql-test/r/innodb_unsafe_binlog.result	06/03/03 22:34:17
drop table if exists t1,t2;
create table t1 (id int not null, f_id int not null, f int not null,
primary key(f_id, id)) engine=innodb;
create table t2 (id int not null,s_id int not null,s varchar(200),
primary key(id)) engine=innodb;
INSERT INTO t1 VALUES (8, 1, 3);
INSERT INTO t1 VALUES (1, 2, 1);
INSERT INTO t2 VALUES (1, 0, '');
INSERT INTO t2 VALUES (8, 1, '');
commit;
DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
WHERE mm.id IS NULL;
select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id)
where mm.id is null lock in share mode;
id	f_id	f
drop table t1,t2;
create table t1(a int not null, b int, primary key(a)) engine=innodb;
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
commit;
set autocommit = 0;
select * from t1 lock in share mode;
a	b
1	1
2	2
3	1
4	2
5	1
6	2
update t1 set b = 5 where b = 1;
set autocommit = 0;
select * from t1 where a = 2 and b = 2 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
commit;
drop table t1;

--- New file ---
+++ mysql-test/t/innodb_unsafe_binlog-master.opt	06/03/03 22:34:17
--innodb_locks_unsafe_for_binlog=true

--- New file ---
+++ mysql-test/t/innodb_unsafe_binlog.test	06/03/03 22:34:17
-- source include/have_innodb.inc
#
# Note that these tests uses a innodb_locks_unsafe_for_binlog option.
#
#
# Test cases for a bug #15650
#

--disable_warnings
drop table if exists t1,t2;
--enable_warnings
create table t1 (id int not null, f_id int not null, f int not null,
primary key(f_id, id)) engine=innodb;
create table t2 (id int not null,s_id int not null,s varchar(200),
primary key(id)) engine=innodb;
INSERT INTO t1 VALUES (8, 1, 3);
INSERT INTO t1 VALUES (1, 2, 1);
INSERT INTO t2 VALUES (1, 0, '');
INSERT INTO t2 VALUES (8, 1, '');
commit;
DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
WHERE mm.id IS NULL;
select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id)
where mm.id is null lock in share mode;
drop table t1,t2;

#
# Test case for unlock row bug where unlock releases all locks granted for
# a row. Only the latest lock should be released.
#

connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
create table t1(a int not null, b int, primary key(a)) engine=innodb;
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
commit;
set autocommit = 0; 
select * from t1 lock in share mode;
update t1 set b = 5 where b = 1;
connection b;
set autocommit = 0;
#
# S-lock to records (2,2),(4,2), and (6,2) should not be released in a update
#
--error 1205
select * from t1 where a = 2 and b = 2 for update;
connection a;
commit;
connection b;
commit;
drop table t1;
disconnect a;
disconnect b;



--- 1.38/storage/innobase/btr/btr0sea.c	2006-02-08 13:58:49 +03:00
+++ 1.39/storage/innobase/btr/btr0sea.c	2006-03-03 22:34:15 +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;
@@ -889,7 +889,8 @@
 void
 btr_search_drop_page_hash_index(
 /*============================*/
-	page_t*	page)	/* in: index page, s- or x-latched */
+	page_t*	page)	/* in: index page, s- or x-latched, or an index page
+			for which we know that block->buf_fix_count == 0 */
 {
 	hash_table_t*	table;
 	buf_block_t*	block;
@@ -904,18 +905,19 @@
 	ulint*		folds;
 	ulint		i;
 	mem_heap_t*	heap;
+	dict_index_t*	index;
 	ulint*		offsets;
 
 #ifdef UNIV_SYNC_DEBUG
 	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);
 
@@ -932,11 +934,16 @@
 
 	n_fields = block->curr_n_fields;
 	n_bytes = block->curr_n_bytes;
+	index = block->index;
 
-	ut_a(n_fields + n_bytes > 0);
+	/* NOTE: The fields of block must not be accessed after
+	releasing btr_search_latch, as the index page might only
+	be s-latched! */
 
 	rw_lock_s_unlock(&btr_search_latch);
 	
+	ut_a(n_fields + n_bytes > 0);
+
 	n_recs = page_get_n_recs(page);
 
 	/* Calculate and cache fold values into an array for fast deletion
@@ -949,33 +956,21 @@
 	rec = page_get_infimum_rec(page);
 	rec = page_rec_get_next(rec);
 
-	if (!page_rec_is_supremum(rec)) {
-		ut_a(n_fields <= rec_get_n_fields(rec, block->index));
-
-		if (n_bytes > 0) {
-			ut_a(n_fields < rec_get_n_fields(rec, block->index));
-		}
-	}
-
 	tree_id = btr_page_get_index_id(page);
 	
+	ut_a(0 == ut_dulint_cmp(tree_id, index->id));
+
 	prev_fold = 0;
 
 	heap = NULL;
 	offsets = NULL;
 
-	if (block->index == NULL) {
-
-		mem_analyze_corruption((byte*)block);
-
-		ut_a(block->index != NULL);
-	}
-
 	while (!page_rec_is_supremum(rec)) {
 		/* FIXME: in a mixed tree, not all records may have enough
 		ordering fields: */
-		offsets = rec_get_offsets(rec, block->index,
-				offsets, n_fields + (n_bytes > 0), &heap);
+		offsets = rec_get_offsets(rec, index, offsets,
+					n_fields + (n_bytes > 0), &heap);
+		ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0));
 		fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
 
 		if (fold == prev_fold && prev_fold != 0) {
@@ -999,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);
@@ -1006,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.75/storage/innobase/dict/dict0dict.c	2006-02-08 13:58:49 +03:00
+++ 1.76/storage/innobase/dict/dict0dict.c	2006-03-03 22:34:15 +03:00
@@ -2104,8 +2104,11 @@
 	dict_table_t*	table,	/* in: table */
 	const char**	columns,/* in: array of column names */
 	ulint		n_cols,	/* in: number of columns */
-	dict_index_t*	types_idx)/* in: NULL or an index to whose types the
-				column types must match */
+	dict_index_t*	types_idx, /* in: NULL or an index to whose types the
+				   column types must match */
+	ibool		check_charsets)	/* in: whether to check charsets.
+					only has an effect if types_idx !=
+					NULL. */
 {
 #ifndef UNIV_HOTBACKUP
 	dict_index_t*	index;
@@ -2135,7 +2138,8 @@
 
 				if (types_idx && !cmp_types_are_equal(
 				     dict_index_get_nth_type(index, i),
-				     dict_index_get_nth_type(types_idx, i))) {
+				     dict_index_get_nth_type(types_idx, i),
+				     check_charsets)) {
 
 				  	break;
 				}		
@@ -2212,7 +2216,8 @@
 /*======================*/
 					/* out: DB_SUCCESS or error code */
 	dict_foreign_t*	foreign,	/* in, own: foreign key constraint */
-	ibool		check_types)	/* in: TRUE=check type compatibility */
+	ibool		check_charsets)	/* in: TRUE=check charset
+					compatibility */
 {
 	dict_table_t*	for_table;
 	dict_table_t*	ref_table;
@@ -2248,16 +2253,10 @@
 	}
 
 	if (for_in_cache->referenced_table == NULL && ref_table) {
-		dict_index_t*	types_idx;
-		if (check_types) {
-			types_idx = for_in_cache->foreign_index;
-		} else {
-			types_idx = NULL;
-		}
 		index = dict_foreign_find_index(ref_table,
 			(const char**) for_in_cache->referenced_col_names,
 			for_in_cache->n_fields,
-			types_idx);
+			for_in_cache->foreign_index, check_charsets);
 
 		if (index == NULL) {
 			dict_foreign_error_report(ef, for_in_cache,
@@ -2281,16 +2280,10 @@
 	}
 
 	if (for_in_cache->foreign_table == NULL && for_table) {
-		dict_index_t*	types_idx;
-		if (check_types) {
-			types_idx = for_in_cache->referenced_index;
-		} else {
-			types_idx = NULL;
-		}
 		index = dict_foreign_find_index(for_table,
 			(const char**) for_in_cache->foreign_col_names,
 			for_in_cache->n_fields,
-			types_idx);
+			for_in_cache->referenced_index, check_charsets);
 
 		if (index == NULL) {
 			dict_foreign_error_report(ef, for_in_cache,
@@ -2810,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),
@@ -3097,7 +3091,7 @@
 	/* Try to find an index which contains the columns
 	as the first fields and in the right order */
 
-	index = dict_foreign_find_index(table, column_names, i, NULL);
+	index = dict_foreign_find_index(table, column_names, i, NULL, TRUE);
 
 	if (!index) {
 		mutex_enter(&dict_foreign_err_mutex);
@@ -3362,8 +3356,7 @@
 
 	if (referenced_table) {
 		index = dict_foreign_find_index(referenced_table,
-						column_names, i,
-						foreign->foreign_index);
+			column_names, i, foreign->foreign_index, TRUE);
 		if (!index) {
 			dict_foreign_free(foreign);
 			mutex_enter(&dict_foreign_err_mutex);

--- 1.44/storage/innobase/dict/dict0load.c	2006-02-08 13:58:50 +03:00
+++ 1.45/storage/innobase/dict/dict0load.c	2006-03-03 22:34:15 +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. */
+
+			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,
+				prtype = dtype_form_prtype(prtype,
 					data_mysql_default_charset_coll);
+			}
 		}
 
 		field = rec_get_nth_field_old(rec, 7, &len);
@@ -1091,7 +1101,7 @@
 				/* out: DB_SUCCESS or error code */
 	const char*	id,	/* in: foreign constraint id as a
 				null-terminated string */
-	ibool		check_types)/* in: TRUE=check type compatibility */
+	ibool		check_charsets)/* in: TRUE=check charset compatibility */
 {	
 	dict_foreign_t*	foreign;
 	dict_table_t*	sys_foreign;
@@ -1204,7 +1214,7 @@
 	a new foreign key constraint but loading one from the data
 	dictionary. */
 
-	return(dict_foreign_add_to_cache(foreign, check_types));
+	return(dict_foreign_add_to_cache(foreign, check_charsets));
 }
 
 /***************************************************************************
@@ -1219,7 +1229,8 @@
 /*===============*/
 					/* out: DB_SUCCESS or error code */
 	const char*	table_name,	/* in: table name */
-	ibool		check_types)	/* in: TRUE=check type compatibility */
+	ibool		check_charsets)	/* in: TRUE=check charset
+					compatibility */
 {
 	btr_pcur_t	pcur;
 	mem_heap_t* 	heap;
@@ -1319,7 +1330,7 @@
 
 	/* Load the foreign constraint definition to the dictionary cache */
 	
-	err = dict_load_foreign(id, check_types);
+	err = dict_load_foreign(id, check_charsets);
 
 	if (err != DB_SUCCESS) {
 		btr_pcur_close(&pcur);

--- 1.61/storage/innobase/fil/fil0fil.c	2006-02-08 13:58:50 +03:00
+++ 1.62/storage/innobase/fil/fil0fil.c	2006-03-03 22:34:15 +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.4/storage/innobase/include/btr0sea.ic	2006-02-08 00:09:57 +03:00
+++ 1.5/storage/innobase/include/btr0sea.ic	2006-03-03 22:34:15 +03:00
@@ -16,7 +16,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 */
 
 /************************************************************************

--- 1.33/storage/innobase/include/buf0buf.h	2005-12-13 23:56:11 +03:00
+++ 1.34/storage/innobase/include/buf0buf.h	2006-03-03 22:34:15 +03:00
@@ -745,8 +745,6 @@
 					buffer pool which are index pages,
 					but this flag is not set because
 					we do not keep track of all pages */
-	dict_index_t*	index;		/* index for which the adaptive
-					hash index has been created */
 	/* 2. Page flushing fields */
 
 	UT_LIST_NODE_T(buf_block_t) flush_list;
@@ -833,7 +831,13 @@
 					records with the same prefix should be
 					indexed in the hash index */
 					
-	/* The following 4 fields are protected by btr_search_latch: */
+	/* These 6 fields may only be modified when we have
+	an x-latch on btr_search_latch AND
+	a) we are holding an s-latch or x-latch on block->lock or
+	b) we know that block->buf_fix_count == 0.
+
+	An exception to this is when we init or create a page
+	in the buffer pool in buf0buf.c. */
 
 	ibool		is_hashed;	/* TRUE if hash index has already been
 					built on this page; note that it does
@@ -850,6 +854,8 @@
 	ulint		curr_side;	/* BTR_SEARCH_LEFT_SIDE or
 					BTR_SEARCH_RIGHT_SIDE in hash
 					indexing */
+	dict_index_t*	index;		/* Index for which the adaptive
+					hash index has been created. */
 	/* 6. Debug fields */
 #ifdef UNIV_SYNC_DEBUG
 	rw_lock_t	debug_latch;	/* in the debug version, each thread

--- 1.23/storage/innobase/include/data0type.h	2006-02-02 01:04:01 +03:00
+++ 1.24/storage/innobase/include/data0type.h	2006-03-03 22:34:15 +03:00
@@ -13,6 +13,7 @@
 
 extern ulint	data_mysql_default_charset_coll;
 #define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8
+#define DATA_MYSQL_BINARY_CHARSET_COLL 63
 
 /* SQL data type struct */
 typedef struct dtype_struct		dtype_t;
@@ -311,7 +312,7 @@
 /*===============*/
 				/* out: padding character code, or
 				ULINT_UNDEFINED if no padding specified */
-	dtype_t*	type);	/* in: type */
+	const dtype_t*	type);	/* in: type */
 /***************************************************************************
 Returns the size of a fixed size data type, 0 if not a fixed size type. */
 UNIV_INLINE

--- 1.28/storage/innobase/include/data0type.ic	2006-02-02 01:04:01 +03:00
+++ 1.29/storage/innobase/include/data0type.ic	2006-03-03 22:34:15 +03:00
@@ -188,26 +188,35 @@
 /*===============*/
 				/* out: padding character code, or
 				ULINT_UNDEFINED if no padding specified */
-	dtype_t*	type)	/* in: type */
+	const dtype_t*	type)	/* in: type */
 {
-	if (type->mtype == DATA_CHAR
-	    || type->mtype == DATA_VARCHAR
-	    || type->mtype == DATA_BINARY
-	    || type->mtype == DATA_FIXBINARY
-	    || type->mtype == DATA_MYSQL
-	    || type->mtype == DATA_VARMYSQL
-	    || (type->mtype == DATA_BLOB
-		&& (type->prtype & DATA_BINARY_TYPE) == 0)) {
-
+	switch (type->mtype) {
+	case DATA_FIXBINARY:
+	case DATA_BINARY:
+		if (UNIV_UNLIKELY(dtype_get_charset_coll(type->prtype)
+		    == DATA_MYSQL_BINARY_CHARSET_COLL)) {
+			/* Starting from 5.0.18, do not pad
+			VARBINARY or BINARY columns. */
+			return(ULINT_UNDEFINED);
+		}
+		/* Fall through */
+	case DATA_CHAR:
+	case DATA_VARCHAR:
+	case DATA_MYSQL:
+	case DATA_VARMYSQL:
 		/* Space is the padding character for all char and binary
 	        strings, and starting from 5.0.3, also for TEXT strings. */
 
-		return((ulint)' ');
+		return(0x20);
+	case DATA_BLOB:
+		if ((type->prtype & DATA_BINARY_TYPE) == 0) {
+			return(0x20);
+		}
+		/* Fall through */
+	default:
+		/* No padding specified */
+		return(ULINT_UNDEFINED);
 	}
-
-	/* No padding specified */
-
-	return(ULINT_UNDEFINED);
 }
 
 /**************************************************************************

--- 1.12/storage/innobase/include/db0err.h	2006-02-09 20:43:04 +03:00
+++ 1.13/storage/innobase/include/db0err.h	2006-03-03 22:34:15 +03:00
@@ -57,10 +57,6 @@
 					buffer pool (for big transactions,
 					InnoDB stores the lock structs in the
 					buffer pool) */
-#define DB_FOREIGN_DUPLICATE_KEY 46	/* foreign key constraints
-					activated by the operation would
-					lead to a duplicate key in some
-					table */
 
 /* The following are partial failure codes */
 #define DB_FAIL 		1000

--- 1.40/storage/innobase/include/dict0dict.h	2005-12-14 02:26:58 +03:00
+++ 1.41/storage/innobase/include/dict0dict.h	2006-03-03 22:34:15 +03:00
@@ -197,7 +197,8 @@
 /*======================*/
 					/* out: DB_SUCCESS or error code */
 	dict_foreign_t*	foreign,	/* in, own: foreign key constraint */
-	ibool		check_types);	/* in: TRUE=check type compatibility */
+	ibool		check_charsets);/* in: TRUE=check charset
+					compatibility */
 /*************************************************************************
 Checks if a table is referenced by foreign keys. */
 

--- 1.11/storage/innobase/include/dict0load.h	2005-12-14 02:26:58 +03:00
+++ 1.12/storage/innobase/include/dict0load.h	2006-03-03 22:34:15 +03:00
@@ -82,7 +82,8 @@
 /*===============*/
 					/* out: DB_SUCCESS or error code */
 	const char*	table_name,	/* in: table name */
-	ibool		check_types);	/* in: TRUE=check type compatibility */
+	ibool		check_charsets);/* in: TRUE=check charsets
+					compatibility */
 /************************************************************************
 Prints to the standard output information on all tables found in the data
 dictionary system table. */

--- 1.44/storage/innobase/include/os0file.h	2006-02-02 01:04:01 +03:00
+++ 1.45/storage/innobase/include/os0file.h	2006-03-03 22:34:15 +03:00
@@ -91,9 +91,10 @@
 #define	OS_FILE_NOT_FOUND		71
 #define	OS_FILE_DISK_FULL		72
 #define	OS_FILE_ALREADY_EXISTS		73
-#define OS_FILE_AIO_RESOURCES_RESERVED	74	/* wait for OS aio resources
+#define	OS_FILE_PATH_ERROR		74
+#define	OS_FILE_AIO_RESOURCES_RESERVED	75	/* wait for OS aio resources
 						to become available again */
-#define	OS_FILE_ERROR_NOT_SPECIFIED	75
+#define	OS_FILE_ERROR_NOT_SPECIFIED	76
 
 /* Types for aio operations */
 #define OS_FILE_READ	10
@@ -187,7 +188,7 @@
 FILE*
 os_file_create_tmpfile(void);
 /*========================*/
-			/* out: temporary file handle (never NULL) */
+			/* out: temporary file handle, or NULL on error */
 /***************************************************************************
 The os_file_opendir() function opens a directory stream corresponding to the
 directory named by the dirname argument. The directory stream is positioned

--- 1.11/storage/innobase/include/rem0cmp.h	2005-12-14 02:26:59 +03:00
+++ 1.12/storage/innobase/include/rem0cmp.h	2006-03-03 22:34:15 +03:00
@@ -24,7 +24,8 @@
 				/* out: TRUE if the types are considered
 				equal in comparisons */
 	dtype_t*	type1,	/* in: type 1 */
-	dtype_t*	type2);	/* in: type 2 */
+	dtype_t*	type2,	/* in: type 2 */
+	ibool		check_charsets); /* in: whether to check charsets */
 /*****************************************************************
 This function is used to compare two data fields for which we know the
 data type. */

--- 1.46/storage/innobase/include/row0mysql.h	2006-02-02 01:04:01 +03:00
+++ 1.47/storage/innobase/include/row0mysql.h	2006-03-03 22:34:16 +03:00
@@ -687,7 +687,6 @@
 #define ROW_READ_TRY_SEMI_CONSISTENT	1
 #define ROW_READ_DID_SEMI_CONSISTENT	2
 
-
 #ifndef UNIV_NONINL
 #include "row0mysql.ic"
 #endif

--- 1.59/storage/innobase/include/srv0srv.h	2006-02-02 17:20:20 +03:00
+++ 1.60/storage/innobase/include/srv0srv.h	2006-03-03 22:34:16 +03:00
@@ -34,6 +34,18 @@
 extern mutex_t	srv_monitor_file_mutex;
 /* Temporary file for innodb monitor output */
 extern FILE*	srv_monitor_file;
+/* Mutex for locking srv_dict_tmpfile.
+This mutex has a very high rank; threads reserving it should not
+be holding any InnoDB latches. */
+extern mutex_t	srv_dict_tmpfile_mutex;
+/* Temporary file for output from the data dictionary */
+extern FILE*	srv_dict_tmpfile;
+/* Mutex for locking srv_misc_tmpfile.
+This mutex has a very low rank; threads reserving it should not
+acquire any further latches or sleep before releasing this one. */
+extern mutex_t	srv_misc_tmpfile_mutex;
+/* Temporary file for miscellanous diagnostic output */
+extern FILE*	srv_misc_tmpfile;
 
 /* Server parameters which are read from the initfile */
 
@@ -65,7 +77,7 @@
 extern ulint	srv_n_log_files;
 extern ulint	srv_log_file_size;
 extern ulint	srv_log_buffer_size;
-extern ulint	srv_flush_log_at_trx_commit;
+extern ulong	srv_flush_log_at_trx_commit;
 
 extern byte	srv_latin1_ordering[256];/* The sort order table of the latin1
 					character set */
@@ -183,7 +195,6 @@
 #define kernel_mutex (*kernel_mutex_temp)
 
 #define SRV_MAX_N_IO_THREADS	100
-#define SRV_CONCURRENCY_THRESHOLD	20
 				
 /* Array of English strings describing the current state of an
 i/o handler thread */

--- 1.8/storage/innobase/include/sync0arr.h	2005-04-08 03:37:33 +04:00
+++ 1.9/storage/innobase/include/sync0arr.h	2006-03-03 22:34:16 +03:00
@@ -66,14 +66,14 @@
         sync_array_t*	arr,	/* in: wait array */
         ulint   	index);  /* in: index of the reserved cell */
 /**********************************************************************
-Frees the cell. NOTE! sync_array_wait_event frees the cell
-automatically! */
+Frees the cell safely by reserving the sync array mutex and decrementing
+n_reserved if necessary. Should only be called from mutex_spin_wait. */
 
 void
-sync_array_free_cell(
-/*=================*/
+sync_array_free_cell_protected(
+/*===========================*/
 	sync_array_t*	arr,	/* in: wait array */
-        ulint    	index);  /* in: index of the cell in array */
+        ulint    	index);	/* in: index of the cell in array */
 /**************************************************************************
 Looks for the cells in the wait array which refer
 to the wait object specified,

--- 1.46/storage/innobase/include/univ.i	2006-02-12 22:33:14 +03:00
+++ 1.47/storage/innobase/include/univ.i	2006-03-03 22:34:16 +03:00
@@ -126,8 +126,14 @@
 #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
 /* If we want to compile a noninlined version we use the following macro
@@ -264,6 +270,9 @@
 #define UNIV_LIKELY(cond) UNIV_EXPECT(cond, TRUE)
 /* Tell the compiler that cond is unlikely to hold */
 #define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE)
+
+/* Compile-time constant of the given array's size. */
+#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 #include <stdio.h>
 #include "ut0dbg.h"

--- 1.65/storage/innobase/lock/lock0lock.c	2006-02-02 01:04:01 +03:00
+++ 1.66/storage/innobase/lock/lock0lock.c	2006-03-03 22:34:16 +03:00
@@ -3761,8 +3761,9 @@
 	rec_t*	rec,		/* in: record */
 	ulint	lock_mode)	/* in: LOCK_S or LOCK_X */
 {
-	lock_t* lock;
-	ulint heap_no;
+	lock_t*	lock;
+	lock_t*	release_lock	= NULL;
+	ulint	heap_no;
 
 	ut_ad(trx && rec);
 
@@ -3772,21 +3773,23 @@
 
 	lock = lock_rec_get_first(rec);
 
-	/* Remove the record lock */
+	/* Find the last lock with the same lock_mode and transaction
+	from the record. */
 
 	while (lock != NULL) {
 		if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
+			release_lock = lock;
 			ut_a(!lock_get_wait(lock));
-
-			lock_rec_reset_nth_bit(lock, heap_no);
-
-			break;
 		}
 
 		lock = lock_rec_get_next(rec, lock);
 	}
 
-	if (UNIV_UNLIKELY(lock == NULL)) {
+	/* If a record lock is found, release the record lock */
+
+	if (UNIV_LIKELY(release_lock != NULL)) {
+		lock_rec_reset_nth_bit(release_lock, heap_no);
+	} else {
 		mutex_exit(&kernel_mutex);
 		ut_print_timestamp(stderr);
 		fprintf(stderr,

--- 1.113/storage/innobase/os/os0file.c	2006-02-02 01:04:02 +03:00
+++ 1.114/storage/innobase/os/os0file.c	2006-03-03 22:34:16 +03:00
@@ -160,15 +160,12 @@
 
 ibool	os_has_said_disk_full	= FALSE;
 
-/* The mutex protecting the following counts of pending pread and pwrite
-operations */
+/* The mutex protecting the following counts of pending I/O operations */
 static os_mutex_t os_file_count_mutex;
 ulint	os_file_n_pending_preads  = 0;
 ulint	os_file_n_pending_pwrites = 0;
-
-/* These are not protected by any mutex */
-ulint os_n_pending_writes = 0;
-ulint os_n_pending_reads = 0;
+ulint	os_n_pending_writes = 0;
+ulint	os_n_pending_reads = 0;
 
 /***************************************************************************
 Gets the operating system version. Currently works only on Windows. */
@@ -314,6 +311,8 @@
 		return(OS_FILE_NOT_FOUND);
 	} else if (err == EEXIST) {
 		return(OS_FILE_ALREADY_EXISTS);
+	} else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
+		return(OS_FILE_PATH_ERROR);
 	} else {
 		return(100 + err);
 	}
@@ -363,7 +362,8 @@
 
 		return(TRUE);
 
-	} else if (err == OS_FILE_ALREADY_EXISTS) {
+	} else if (err == OS_FILE_ALREADY_EXISTS
+			|| err == OS_FILE_PATH_ERROR) {
 
 		return(FALSE);
 	} else {
@@ -467,7 +467,8 @@
 
 		return(TRUE);
 
-	} else if (err == OS_FILE_ALREADY_EXISTS) {
+	} else if (err == OS_FILE_ALREADY_EXISTS
+			|| err == OS_FILE_PATH_ERROR) {
 
 		return(FALSE);
 	} else {
@@ -1905,12 +1906,14 @@
 #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
         os_mutex_enter(os_file_count_mutex);
 	os_file_n_pending_preads++;
+	os_n_pending_reads++;
         os_mutex_exit(os_file_count_mutex);
 
         n_bytes = pread(file, buf, (ssize_t)n, offs);
 
         os_mutex_enter(os_file_count_mutex);
 	os_file_n_pending_preads--;
+	os_n_pending_reads--;
         os_mutex_exit(os_file_count_mutex);
 
 	return(n_bytes);
@@ -1920,6 +1923,10 @@
 	ssize_t	ret;
 	ulint	i;
 
+        os_mutex_enter(os_file_count_mutex);
+	os_n_pending_reads++;
+        os_mutex_exit(os_file_count_mutex);
+
 	/* Protect the seek / read operation with a mutex */
 	i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 	
@@ -1928,15 +1935,17 @@
 	ret_offset = lseek(file, offs, SEEK_SET);
 
 	if (ret_offset < 0) {
-		os_mutex_exit(os_file_seek_mutexes[i]);
-
-		return(-1);
+		ret = -1;
+	} else {
+		ret = read(file, buf, (ssize_t)n);
 	}
-	
-	ret = read(file, buf, (ssize_t)n);
 
 	os_mutex_exit(os_file_seek_mutexes[i]);
 
+        os_mutex_enter(os_file_count_mutex);
+	os_n_pending_reads--;
+        os_mutex_exit(os_file_count_mutex);
+
 	return(ret);
 	}
 #endif
@@ -1981,12 +1990,14 @@
 #if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
         os_mutex_enter(os_file_count_mutex);
 	os_file_n_pending_pwrites++;
+	os_n_pending_writes++;
         os_mutex_exit(os_file_count_mutex);
 
 	ret = pwrite(file, buf, (ssize_t)n, offs);
 
         os_mutex_enter(os_file_count_mutex);
 	os_file_n_pending_pwrites--;
+	os_n_pending_writes--;
         os_mutex_exit(os_file_count_mutex);
 
 # ifdef UNIV_DO_FLUSH
@@ -2008,6 +2019,10 @@
 	off_t	ret_offset;
 	ulint	i;
 
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_writes++;
+	os_mutex_exit(os_file_count_mutex);
+
 	/* Protect the seek / write operation with a mutex */
 	i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 	
@@ -2016,9 +2031,9 @@
 	ret_offset = lseek(file, offs, SEEK_SET);
 
 	if (ret_offset < 0) {
-		os_mutex_exit(os_file_seek_mutexes[i]);
+		ret = -1;
 
-		return(-1);
+		goto func_exit;
 	}
 	
 	ret = write(file, buf, (ssize_t)n);
@@ -2036,8 +2051,13 @@
 	}
 # endif /* UNIV_DO_FLUSH */
 
+func_exit:
 	os_mutex_exit(os_file_seek_mutexes[i]);
 
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_writes--;
+	os_mutex_exit(os_file_count_mutex);
+
 	return(ret);
 	}
 #endif
@@ -2082,9 +2102,13 @@
 	low = (DWORD) offset;
 	high = (DWORD) offset_high;
 
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_reads++;
+	os_mutex_exit(os_file_count_mutex);
+
 	/* Protect the seek / read operation with a mutex */
 	i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
-	
+
 	os_mutex_enter(os_file_seek_mutexes[i]);
 
 	ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
@@ -2093,17 +2117,21 @@
 
 		os_mutex_exit(os_file_seek_mutexes[i]);
 
+		os_mutex_enter(os_file_count_mutex);
+		os_n_pending_reads--;
+		os_mutex_exit(os_file_count_mutex);
+
 		goto error_handling;
 	} 
 	
-        os_n_pending_reads++;
-        
 	ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
 
-        os_n_pending_reads--;
-
 	os_mutex_exit(os_file_seek_mutexes[i]);
 	
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_reads--;
+	os_mutex_exit(os_file_count_mutex);
+
 	if (ret && len == n) {
 		return(TRUE);
 	}		
@@ -2114,12 +2142,8 @@
 	os_bytes_read_since_printout += n;
 
 try_again:
-        os_n_pending_reads++;
-        
 	ret = os_file_pread(file, buf, n, offset, offset_high);
 
-        os_n_pending_reads--;
-
 	if ((ulint)ret == n) {
 
 		return(TRUE);
@@ -2193,6 +2217,10 @@
 	low = (DWORD) offset;
 	high = (DWORD) offset_high;
 
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_reads++;
+	os_mutex_exit(os_file_count_mutex);
+
 	/* Protect the seek / read operation with a mutex */
 	i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 	
@@ -2204,17 +2232,21 @@
 
 		os_mutex_exit(os_file_seek_mutexes[i]);
 
+		os_mutex_enter(os_file_count_mutex);
+		os_n_pending_reads--;
+		os_mutex_exit(os_file_count_mutex);
+
 		goto error_handling;
 	} 
 	
-        os_n_pending_reads++;
-        
 	ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
 
-        os_n_pending_reads--;
-        
 	os_mutex_exit(os_file_seek_mutexes[i]);
 	
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_reads--;
+	os_mutex_exit(os_file_count_mutex);
+
 	if (ret && len == n) {
 		return(TRUE);
 	}		
@@ -2225,12 +2257,8 @@
 	os_bytes_read_since_printout += n;
 
 try_again:
-        os_n_pending_reads++;
-
 	ret = os_file_pread(file, buf, n, offset, offset_high);
 
-        os_n_pending_reads--;
-
 	if ((ulint)ret == n) {
 
 		return(TRUE);
@@ -2310,6 +2338,10 @@
 	low = (DWORD) offset;
 	high = (DWORD) offset_high;
 	
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_writes++;
+	os_mutex_exit(os_file_count_mutex);
+
 	/* Protect the seek / write operation with a mutex */
 	i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 	
@@ -2321,6 +2353,10 @@
 
 		os_mutex_exit(os_file_seek_mutexes[i]);
 		
+		os_mutex_enter(os_file_count_mutex);
+		os_n_pending_writes--;
+		os_mutex_exit(os_file_count_mutex);
+
 		ut_print_timestamp(stderr);
 
 		fprintf(stderr,
@@ -2335,12 +2371,8 @@
 		return(FALSE);
 	} 
 
-        os_n_pending_writes++;
-        
 	ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
 
-        os_n_pending_writes--;
-	
 	/* Always do fsync to reduce the probability that when the OS crashes,
 	a database page is only partially physically written to disk. */
 
@@ -2352,6 +2384,10 @@
 
 	os_mutex_exit(os_file_seek_mutexes[i]);
 
+	os_mutex_enter(os_file_count_mutex);
+	os_n_pending_writes--;
+	os_mutex_exit(os_file_count_mutex);
+
 	if (ret && len == n) {
 
 		return(TRUE);
@@ -2402,11 +2438,7 @@
 #else
 	ssize_t	ret;
 	
-        os_n_pending_writes++;
-        
 	ret = os_file_pwrite(file, buf, n, offset, offset_high);
-
-        os_n_pending_writes--;
         
 	if ((ulint)ret == n) {
 

--- 1.28/storage/innobase/os/os0sync.c	2006-02-08 13:58:50 +03:00
+++ 1.29/storage/innobase/os/os0sync.c	2006-03-03 22:34:16 +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.32/storage/innobase/os/os0thread.c	2006-02-12 22:33:15 +03:00
+++ 1.33/storage/innobase/os/os0thread.c	2006-03-03 22:34:16 +03:00
@@ -157,15 +157,6 @@
 		 exit(1);
 	}
 #endif
-#ifdef __NETWARE__
-	ret = pthread_attr_setstacksize(&attr,
-			      (size_t)NW_THD_STACKSIZE);
-        if (ret) {
-	         fprintf(stderr,
-          "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret);
-		 exit(1);
-	}
-#endif
 	os_mutex_enter(os_sync_mutex);
 	os_thread_count++;
 	os_mutex_exit(os_sync_mutex);

--- 1.31/storage/innobase/rem/rem0cmp.c	2005-12-14 02:26:59 +03:00
+++ 1.32/storage/innobase/rem/rem0cmp.c	2006-03-03 22:34:16 +03:00
@@ -99,7 +99,8 @@
 				/* out: TRUE if the types are considered
 				equal in comparisons */
 	dtype_t*	type1,	/* in: type 1 */
-	dtype_t*	type2)	/* in: type 2 */
+	dtype_t*	type2,	/* in: type 2 */
+	ibool		check_charsets) /* in: whether to check charsets */
 {
 	if (dtype_is_non_binary_string_type(type1->mtype, type1->prtype)
 	    && dtype_is_non_binary_string_type(type2->mtype, type2->prtype)) {
@@ -107,12 +108,12 @@
 		/* Both are non-binary string types: they can be compared if
 		and only if the charset-collation is the same */
 
-		if (dtype_get_charset_coll(type1->prtype)
-				== dtype_get_charset_coll(type2->prtype)) {
+		if (check_charsets) {
+			return(dtype_get_charset_coll(type1->prtype)
+			    == dtype_get_charset_coll(type2->prtype));
+		} else {
 			return(TRUE);
 		}
-
-		return(FALSE);
         }
 
 	if (dtype_is_binary_string_type(type1->mtype, type1->prtype)

--- 1.76/storage/innobase/row/row0ins.c	2006-02-09 20:43:04 +03:00
+++ 1.77/storage/innobase/row/row0ins.c	2006-03-03 22:34:16 +03:00
@@ -549,6 +549,15 @@
 					default:
 						ut_error;
 					case 1:
+						if (UNIV_UNLIKELY(
+							dtype_get_charset_coll(
+							dtype_get_prtype(type))
+					== DATA_MYSQL_BINARY_CHARSET_COLL)) {
+						    /* Do not pad BINARY
+						    columns. */
+						    return(ULINT_UNDEFINED);
+						}
+
 						/* space=0x20 */
 						memset(pad_start, 0x20,
 							pad_end - pad_start);
@@ -588,20 +597,21 @@
 	trx_t*		trx,		/* in: transaction */
 	dict_foreign_t*	foreign)	/* in: foreign key constraint */
 {
-		
-	FILE*	tf = os_file_create_tmpfile();
-
-	if (tf) {
-		ut_print_name(tf, trx, foreign->foreign_table_name);
-		dict_print_info_on_foreign_key_in_create_format(tf, trx,
-			foreign, FALSE);
+	mutex_enter(&srv_misc_tmpfile_mutex);
+	rewind(srv_misc_tmpfile);
 
-		trx_set_detailed_error_from_file(trx, tf);
-
-		fclose(tf);
+	if (os_file_set_eof(srv_misc_tmpfile)) {
+		ut_print_name(srv_misc_tmpfile, trx,
+				foreign->foreign_table_name);
+		dict_print_info_on_foreign_key_in_create_format(
+				srv_misc_tmpfile,
+				trx, foreign, FALSE);
+		trx_set_detailed_error_from_file(trx, srv_misc_tmpfile);
 	} else {
-		trx_set_detailed_error(trx, "temp file creation failed");
+		trx_set_detailed_error(trx, "temp file operation failed");
 	}
+
+	mutex_exit(&srv_misc_tmpfile_mutex);
 }
 
 /*************************************************************************
@@ -709,7 +719,7 @@
 	}
 
 	if (rec) {
-		rec_print(ef, rec, foreign->foreign_index);
+		rec_print(ef, rec, foreign->referenced_index);
 	}
 	putc('\n', ef);
 
@@ -1376,21 +1386,6 @@
 						thr, foreign, &pcur, entry,
 									&mtr);
 					if (err != DB_SUCCESS) {
-						/* Since reporting a plain
-						"duplicate key" error
-						message to the user in
-						cases where a long CASCADE
-						operation would lead to a
-						duplicate key in some
-						other table is very
-						confusing, map duplicate
-						key errors resulting from
-						FK constraints to a
-						separate error code. */
-				    
-						if (err == DB_DUPLICATE_KEY) {
-						    err = DB_FOREIGN_DUPLICATE_KEY;
-						}
 
 						break;
 					}

--- 1.121/storage/innobase/row/row0mysql.c	2006-02-09 20:43:04 +03:00
+++ 1.122/storage/innobase/row/row0mysql.c	2006-03-03 22:34:16 +03:00
@@ -473,9 +473,8 @@
 	ut_a(err != DB_SUCCESS);
 	
 	trx->error_state = DB_SUCCESS;
-	
-	if ((err == DB_DUPLICATE_KEY)
-		|| (err == DB_FOREIGN_DUPLICATE_KEY)) {
+
+	if (err == DB_DUPLICATE_KEY) {
            	if (savept) {
 			/* Roll back the latest, possibly incomplete
 			insertion or update */
@@ -2127,7 +2126,7 @@
 
 	if (err == DB_SUCCESS) {
 		/* Check that also referencing constraints are ok */
-		err = dict_load_foreigns(name, trx->check_foreigns);
+		err = dict_load_foreigns(name, TRUE);
 	}
 
 	if (err != DB_SUCCESS) {
@@ -3586,7 +3585,8 @@
 	mem_heap_t*	heap			= NULL;
 	const char**	constraints_to_drop	= NULL;
 	ulint		n_constraints_to_drop	= 0;
-        ibool           recovering_temp_table   = FALSE;
+	ibool           recovering_temp_table   = FALSE;
+	ibool		old_is_tmp, new_is_tmp;
 	ulint		len;
 	ulint		i;
         ibool		success;
@@ -3626,6 +3626,9 @@
 	trx->op_info = "renaming table";
 	trx_start_if_not_started(trx);
 
+	old_is_tmp = row_is_mysql_tmp_table_name(old_name);
+	new_is_tmp = row_is_mysql_tmp_table_name(new_name);
+	
 	if (row_mysql_is_recovered_tmp_table(new_name)) {
 
                 recovering_temp_table = TRUE;
@@ -3672,7 +3675,7 @@
 	len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
 		+ ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
 
-	if (row_is_mysql_tmp_table_name(new_name)) {
+	if (new_is_tmp) {
 		db_name_len = dict_get_db_name_len(old_name) + 1;
 
 		/* MySQL is doing an ALTER TABLE command and it renames the
@@ -3825,7 +3828,7 @@
 		the table is stored in a single-table tablespace */
 
 		success = dict_table_rename_in_cache(table, new_name,
-				!row_is_mysql_tmp_table_name(new_name));
+				!new_is_tmp);
 		if (!success) {
 			trx->error_state = DB_SUCCESS;
 			trx_general_rollback_for_mysql(trx, FALSE, NULL);
@@ -3842,19 +3845,16 @@
 			goto funct_exit;
 		}
 
-		err = dict_load_foreigns(new_name, trx->check_foreigns);
-
-		if (row_is_mysql_tmp_table_name(old_name)) {
+		/* We only want to switch off some of the type checking in
+		an ALTER, not in a RENAME. */
+		
+		err = dict_load_foreigns(new_name,
+			old_is_tmp ? trx->check_foreigns : TRUE);
 
-			/* MySQL is doing an ALTER TABLE command and it
-			renames the created temporary table to the name
-			of the original table. In the ALTER TABLE we maybe
-			created some FOREIGN KEY constraints for the temporary
-			table. But we want to load also the foreign key
-			constraint definitions for the original table name. */
+		if (err != DB_SUCCESS) {
+			ut_print_timestamp(stderr);
 
-			if (err != DB_SUCCESS) {
-	    			ut_print_timestamp(stderr);
+			if (old_is_tmp) {
 				fputs("  InnoDB: Error: in ALTER TABLE ",
 					stderr);
 				ut_print_name(stderr, trx, new_name);
@@ -3862,36 +3862,23 @@
 	"InnoDB: has or is referenced in foreign key constraints\n"
 	"InnoDB: which are not compatible with the new table definition.\n",
 					stderr);
-
-				ut_a(dict_table_rename_in_cache(table,
-					old_name, FALSE));
-				trx->error_state = DB_SUCCESS;
-				trx_general_rollback_for_mysql(trx, FALSE,
-									NULL);
-				trx->error_state = DB_SUCCESS;
-			}
-		} else {
-			if (err != DB_SUCCESS) {
-
-	    			ut_print_timestamp(stderr);
-
+			} else {
 				fputs(
 				"  InnoDB: Error: in RENAME TABLE table ",
 					stderr);
 				ut_print_name(stderr, trx, new_name);
 				fputs("\n"
-     "InnoDB: is referenced in foreign key constraints\n"
-     "InnoDB: which are not compatible with the new table definition.\n",
+	"InnoDB: is referenced in foreign key constraints\n"
+	"InnoDB: which are not compatible with the new table definition.\n",
 					stderr);
-     
-				ut_a(dict_table_rename_in_cache(table,
-					old_name, FALSE));
-						
-				trx->error_state = DB_SUCCESS;
-				trx_general_rollback_for_mysql(trx, FALSE,
-									NULL);
-				trx->error_state = DB_SUCCESS;
 			}
+
+			ut_a(dict_table_rename_in_cache(table,
+					old_name, FALSE));
+			trx->error_state = DB_SUCCESS;
+			trx_general_rollback_for_mysql(trx, FALSE,
+				NULL);
+			trx->error_state = DB_SUCCESS;
 		}
 	}
 funct_exit:	

--- 1.100/storage/innobase/row/row0sel.c	2006-02-02 01:04:02 +03:00
+++ 1.101/storage/innobase/row/row0sel.c	2006-03-03 22:34:16 +03:00
@@ -4085,9 +4085,9 @@
 	/* We have an optimization to save CPU time: if this is a consistent
 	read on a unique condition on the clustered index, then we do not
 	store the pcur position, because any fetch next or prev will anyway
-	return 'end of file'. An exception is the MySQL HANDLER command
-	where the user can move the cursor with PREV or NEXT even after
-	a unique search. */
+	return 'end of file'. Exceptions are locking reads and the MySQL 
+	HANDLER command where the user can move the cursor with PREV or NEXT 
+	even after a unique search. */
 
 	if (!unique_search_from_clust_index
 	    || prebuilt->select_lock_type != LOCK_NONE
@@ -4176,6 +4176,7 @@
 	did_semi_consistent_read = FALSE;
 
 	/*-------------------------------------------------------------*/
+
 	btr_pcur_store_position(pcur, &mtr);
 
 	mtr_commit(&mtr);

--- 1.96/storage/innobase/srv/srv0srv.c	2006-02-02 17:20:29 +03:00
+++ 1.97/storage/innobase/srv/srv0srv.c	2006-03-03 22:34:16 +03:00
@@ -113,7 +113,7 @@
 ulint	srv_n_log_files		= ULINT_MAX;
 ulint	srv_log_file_size	= ULINT_MAX;	/* size in database pages */ 
 ulint	srv_log_buffer_size	= ULINT_MAX;	/* size in database pages */ 
-ulint	srv_flush_log_at_trx_commit = 1;
+ulong	srv_flush_log_at_trx_commit = 1;
 
 byte	srv_latin1_ordering[256]	/* The sort order table of the latin1
 					character set. The following table is
@@ -258,9 +258,10 @@
 we could get a deadlock. MySQL creates a thread for each user session, and
 semaphore contention and convoy problems can occur withput this restriction.
 Value 10 should be good if there are less than 4 processors + 4 disks in the
-computer. Bigger computers need bigger values. */
+computer. Bigger computers need bigger values. Value 0 will disable the
+concurrency check. */
 
-ulong	srv_thread_concurrency	= SRV_CONCURRENCY_THRESHOLD;
+ulong	srv_thread_concurrency	= 0;
 ulong   srv_commit_concurrency  = 0;
 
 os_fast_mutex_t	srv_conc_mutex;		/* this mutex protects srv_conc data
@@ -397,6 +398,18 @@
 mutex_t	srv_monitor_file_mutex;
 /* Temporary file for innodb monitor output */
 FILE*	srv_monitor_file;
+/* Mutex for locking srv_dict_tmpfile.
+This mutex has a very high rank; threads reserving it should not
+be holding any InnoDB latches. */
+mutex_t	srv_dict_tmpfile_mutex;
+/* Temporary file for output from the data dictionary */
+FILE*	srv_dict_tmpfile;
+/* Mutex for locking srv_misc_tmpfile.
+This mutex has a very low rank; threads reserving it should not
+acquire any further latches or sleep before releasing this one. */
+mutex_t	srv_misc_tmpfile_mutex;
+/* Temporary file for miscellanous diagnostic output */
+FILE*	srv_misc_tmpfile;
 
 ulint	srv_main_thread_process_no	= 0;
 ulint	srv_main_thread_id		= 0;
@@ -1129,7 +1142,7 @@
 	trx_t*	trx)	/* in: transaction object associated with the
 			thread */
 {
-	if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) {
+	if (UNIV_LIKELY(!srv_thread_concurrency)) {
 	
 		return;
 	}
@@ -1155,7 +1168,7 @@
 {
 	srv_conc_slot_t*	slot	= NULL;
 
-	if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) {
+	if (UNIV_LIKELY(!srv_thread_concurrency)) {
 	
 		return;
 	}

--- 1.90/storage/innobase/srv/srv0start.c	2006-02-08 13:58:50 +03:00
+++ 1.91/storage/innobase/srv/srv0start.c	2006-03-03 22:34:16 +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 */
@@ -1180,6 +1194,20 @@
 		}
 	}
 
+	mutex_create(&srv_dict_tmpfile_mutex);
+	mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
+	srv_dict_tmpfile = os_file_create_tmpfile();
+	if (!srv_dict_tmpfile) {
+		return(DB_ERROR);
+	}
+
+	mutex_create(&srv_misc_tmpfile_mutex);
+	mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
+	srv_misc_tmpfile = os_file_create_tmpfile();
+	if (!srv_misc_tmpfile) {
+		return(DB_ERROR);
+	}
+
 	/* Restrict the maximum number of file i/o threads */
 	if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) {
 
@@ -1822,8 +1850,19 @@
 			mem_free(srv_monitor_file_name);
 		}
 	}
-	
+	if (srv_dict_tmpfile) {
+		fclose(srv_dict_tmpfile);
+		srv_dict_tmpfile = 0;
+	}
+
+	if (srv_misc_tmpfile) {
+		fclose(srv_misc_tmpfile);
+		srv_misc_tmpfile = 0;
+	}
+
 	mutex_free(&srv_monitor_file_mutex);
+	mutex_free(&srv_dict_tmpfile_mutex);
+	mutex_free(&srv_misc_tmpfile_mutex);
 
 	/* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
 	them */

--- 1.21/storage/innobase/sync/sync0arr.c	2005-04-08 03:37:36 +04:00
+++ 1.22/storage/innobase/sync/sync0arr.c	2006-03-03 22:34:17 +03:00
@@ -46,9 +46,18 @@
 until a resource is released. The suspending is implemented
 using an operating system event semaphore. */
 struct sync_cell_struct {
+	/* State of the cell. SC_WAKING_UP means
+	sync_array_struct->n_reserved has been decremented, but the thread
+	in this cell has not waken up yet. When it does, it will set the
+	state to SC_FREE. Note that this is done without the protection of
+	any mutex. */
+	enum { SC_FREE, SC_RESERVED, SC_WAKING_UP } state;
+	
         void*           wait_object;    /* pointer to the object the
-                                        thread is waiting for; if NULL
-                                        the cell is free for use */
+					thread is waiting for; this is not
+					reseted to NULL when a cell is
+					freed. */
+
 	mutex_t*	old_wait_mutex;	/* the latest wait mutex in cell */
 	rw_lock_t*	old_wait_rw_lock;/* the latest wait rw-lock in cell */
         ulint		request_type;	/* lock type requested on the
@@ -69,11 +78,6 @@
 					the wait cell */
 };
 
-/* NOTE: It is allowed for a thread to wait
-for an event allocated for the array without owning the
-protecting mutex (depending on the case: OS or database mutex), but
-all changes (set or reset) to the state of the event must be made
-while owning the mutex. */
 struct sync_array_struct {
 	ulint		n_reserved;	/* number of currently reserved
 					cells in the wait array */
@@ -217,7 +221,8 @@
 
         for (i = 0; i < n_cells; i++) {
 		cell = sync_array_get_nth_cell(arr, i);        	
-                cell->wait_object = NULL;
+		cell->state = SC_FREE;
+		cell->wait_object = NULL;
 
                 /* Create an operating system event semaphore with no name */
                 cell->event = os_event_create(NULL);
@@ -282,7 +287,7 @@
         for (i = 0; i < arr->n_cells; i++) {
 		cell = sync_array_get_nth_cell(arr, i);        	
 
-                if (cell->wait_object != NULL) {
+                if (cell->state == SC_RESERVED) {
                         count++;
                 }
         }
@@ -292,30 +297,6 @@
         sync_array_exit(arr);
 }
 
-/***********************************************************************
-Puts the cell event in set state. */
-static
-void
-sync_cell_event_set(
-/*================*/
-	sync_cell_t*	cell)	/* in: array cell */
-{
-	os_event_set(cell->event);
-	cell->event_set = TRUE;
-}		
-
-/***********************************************************************
-Puts the cell event in reset state. */
-static
-void
-sync_cell_event_reset(
-/*==================*/
-	sync_cell_t*	cell)	/* in: array cell */
-{
-	os_event_reset(cell->event);
-	cell->event_set = FALSE;
-}		
-
 /**********************************************************************
 Reserves a wait array cell for waiting for an object.
 The event of the cell is reset to nonsignalled state. */
@@ -344,13 +325,18 @@
         for (i = 0; i < arr->n_cells; i++) {
 		cell = sync_array_get_nth_cell(arr, i);        	
 
-                if (cell->wait_object == NULL) {
+                if (cell->state == SC_FREE) {
 
-                        /* Make sure the event is reset */
-			if (cell->event_set) {	
-                        	sync_cell_event_reset(cell);
-			}
+			/* We do not check cell->event_set because it is
+			set outside the protection of the sync array mutex
+			and we had a bug regarding it, and since resetting
+			an event when it is not needed does no harm it is
+			safer always to do it. */
+			
+			cell->event_set = FALSE;
+			os_event_reset(cell->event);
 
+			cell->state = SC_RESERVED;
 			cell->reservation_time = time(NULL);
 			cell->thread = os_thread_get_curr_id();
 
@@ -384,6 +370,68 @@
 }
 
 /**********************************************************************
+Frees the cell. Note that we don't have any mutex reserved when calling
+this. */
+static
+void
+sync_array_free_cell(
+/*=================*/
+	sync_array_t*	arr,	/* in: wait array */
+        ulint    	index)  /* in: index of the cell in array */
+{
+	sync_cell_t*   	cell;
+
+	cell = sync_array_get_nth_cell(arr, index);
+
+	ut_a(cell->state == SC_WAKING_UP);
+	ut_a(cell->wait_object != NULL);
+
+	cell->state = SC_FREE;
+}
+
+/**********************************************************************
+Frees the cell safely by reserving the sync array mutex and decrementing
+n_reserved if necessary. Should only be called from mutex_spin_wait. */
+
+void
+sync_array_free_cell_protected(
+/*===========================*/
+	sync_array_t*	arr,	/* in: wait array */
+	ulint		index)	/* in: index of the cell in array */
+{
+	sync_cell_t*	cell;
+
+	sync_array_enter(arr);
+	
+	cell = sync_array_get_nth_cell(arr, index);
+
+	ut_a(cell->state != SC_FREE);
+	ut_a(cell->wait_object != NULL);
+	
+	/* We only need to decrement n_reserved if it has not already been
+	done by sync_array_signal_object. */
+	if (cell->state == SC_RESERVED) {
+		ut_a(arr->n_reserved > 0);
+		arr->n_reserved--;
+	} else if (cell->state == SC_WAKING_UP) {
+		/* This is tricky; if we don't wait for the event to be
+		signaled, signal_object can set the state of a cell to
+		SC_WAKING_UP, mutex_spin_wait can call this and set the
+		state to SC_FREE, and then signal_object gets around to
+		calling os_set_event for the cell but since it's already
+		been freed things break horribly. */
+		
+		sync_array_exit(arr);
+		os_event_wait(cell->event);
+		sync_array_enter(arr);
+	}
+
+	cell->state = SC_FREE;
+
+	sync_array_exit(arr);
+}
+
+/**********************************************************************
 This function should be called when a thread starts to wait on
 a wait array cell. In the debug version this function checks
 if the wait for a semaphore will result in a deadlock, in which
@@ -400,10 +448,9 @@
         
         ut_a(arr);
 
-        sync_array_enter(arr);
-
 	cell = sync_array_get_nth_cell(arr, index);        	
 
+	ut_a((cell->state == SC_RESERVED) || (cell->state == SC_WAKING_UP));
 	ut_a(cell->wait_object);
 	ut_a(!cell->waiting);
 	ut_ad(os_thread_get_curr_id() == cell->thread);
@@ -418,6 +465,7 @@
 	recursively sync_array routines, leading to trouble.
 	rw_lock_debug_mutex freezes the debug lists. */
 
+	sync_array_enter(arr);
 	rw_lock_debug_mutex_enter();
 
 	if (TRUE == sync_array_detect_deadlock(arr, cell, cell, 0)) {
@@ -427,16 +475,16 @@
 	}		
 
 	rw_lock_debug_mutex_exit();
+	sync_array_exit(arr);
 #endif
-        sync_array_exit(arr);
-
         os_event_wait(event);
 
         sync_array_free_cell(arr, index);
 }
 
 /**********************************************************************
-Reports info of a wait array cell. */
+Reports info of a wait array cell. Note: sync_array_print_long_waits()
+calls this without mutex protection. */
 static
 void
 sync_array_cell_print(
@@ -455,8 +503,17 @@
 			(ulong) os_thread_pf(cell->thread), cell->file,
 		       (ulong) cell->line,
 		       difftime(time(NULL), cell->reservation_time));
+	fprintf(file, "Wait array cell state %lu\n", (ulong)cell->state);
+
+	/* If the memory area pointed to by old_wait_mutex /
+	old_wait_rw_lock has been freed, this can crash. */
+	
+	if (cell->state != SC_RESERVED) {
+		/* If cell has this state, then even if we are holding the sync
+		array mutex, the wait object may get freed meanwhile. Do not
+		print the wait object then. */
 
-	if (type == SYNC_MUTEX) {
+	} else if (type == SYNC_MUTEX) {
 		/* We use old_wait_mutex in case the cell has already
 		been freed meanwhile */
 		mutex = cell->old_wait_mutex;
@@ -507,10 +564,6 @@
 		ut_error;
 	}
 
-        if (!cell->waiting) {
-		fputs("wait has ended\n", file);
-	}
-
         if (cell->event_set) {
 		fputs("wait is ending\n", file);
 	}
@@ -535,7 +588,7 @@
 
 		cell = sync_array_get_nth_cell(arr, i);        	
 
-                if (cell->wait_object != NULL
+                if ((cell->state == SC_RESERVED)
 		    && os_thread_eq(cell->thread, thread)) {
 
 		    	return(cell);	/* Found */
@@ -617,6 +670,7 @@
 	rw_lock_debug_t*debug;
 	
         ut_a(arr && start && cell);
+	ut_ad(cell->state == SC_RESERVED);
 	ut_ad(cell->wait_object);
 	ut_ad(os_thread_get_curr_id() == start->thread);
 	ut_ad(depth < 100);
@@ -649,7 +703,8 @@
 			if (ret) {
 				fprintf(stderr,
 			"Mutex %p owned by thread %lu file %s line %lu\n",
-					mutex, (ulong) os_thread_pf(mutex->thread_id),
+					mutex,
+					(ulong) os_thread_pf(mutex->thread_id),
 					mutex->file_name, (ulong) mutex->line);
 				sync_array_cell_print(stderr, cell);
 
@@ -784,32 +839,6 @@
 	return(FALSE);
 }
 
-/**********************************************************************
-Frees the cell. NOTE! sync_array_wait_event frees the cell
-automatically! */
-
-void
-sync_array_free_cell(
-/*=================*/
-	sync_array_t*	arr,	/* in: wait array */
-        ulint    	index)  /* in: index of the cell in array */
-{
-        sync_cell_t*   	cell;
-        
-        sync_array_enter(arr);
-
-        cell = sync_array_get_nth_cell(arr, index);
-
-        ut_a(cell->wait_object != NULL);
-
-	cell->wait_object =  NULL;
-
-	ut_a(arr->n_reserved > 0);
-	arr->n_reserved--;
-
-        sync_array_exit(arr);
-}
-
 /**************************************************************************
 Looks for the cells in the wait array which refer to the wait object
 specified, and sets their corresponding events to the signaled state. In this
@@ -825,6 +854,21 @@
         sync_cell_t*   	cell;
         ulint           count;
         ulint           i;
+	ulint		res_count;
+
+	/* We store the addresses of cells we need to signal and signal
+	them only after we have released the sync array's mutex (for
+	performance reasons). cell_count is the number of such cells, and
+	cell_ptr points to the first one. If there are less than
+	UT_ARR_SIZE(cells) of them, cell_ptr == &cells[0], otherwise
+	cell_ptr points to malloc'd memory that we must free. */
+
+	sync_cell_t*	cells[100];
+	sync_cell_t**	cell_ptr = &cells[0];
+	ulint		cell_count = 0;
+	ulint		cell_max_count = UT_ARR_SIZE(cells);
+	
+	ut_a(100 == cell_max_count);
 
         sync_array_enter(arr);
 
@@ -833,16 +877,44 @@
 	i = 0;
 	count = 0;
 
-        while (count < arr->n_reserved) {
+	/* We need to store this to a local variable because it is modified
+	inside the loop */
+	res_count = arr->n_reserved;
+	
+        while (count < res_count) {
 
         	cell = sync_array_get_nth_cell(arr, i);
 
-                if (cell->wait_object != NULL) {
+                if (cell->state == SC_RESERVED) {
 
                         count++;
                         if (cell->wait_object == object) {
+				cell->state = SC_WAKING_UP;
 
-                        	sync_cell_event_set(cell);
+				ut_a(arr->n_reserved > 0);
+				arr->n_reserved--;
+				
+				if (cell_count == cell_max_count) {
+					sync_cell_t** old_cell_ptr = cell_ptr;
+					size_t old_size = cell_max_count *
+						sizeof(sync_cell_t*);
+					cell_max_count *= 2;
+
+					size_t new_size = cell_max_count *
+						sizeof(sync_cell_t*);
+
+					cell_ptr = malloc(new_size);
+					ut_a(cell_ptr);
+					memcpy(cell_ptr, old_cell_ptr,
+						old_size);
+
+					if (old_cell_ptr != &cells[0]) {
+						free(old_cell_ptr);
+					}
+				}
+
+				cell_ptr[cell_count] = cell;
+				cell_count++;
                         }
                 }
 
@@ -850,12 +922,27 @@
         }
 
         sync_array_exit(arr);
+
+	for (i = 0; i < cell_count; i++) {
+		cell = cell_ptr[i];
+
+		cell->event_set = TRUE;
+		os_event_set(cell->event);
+	}
+
+	if (cell_ptr != &cells[0]) {
+		free(cell_ptr);
+	}
 }
 
 /**************************************************************************
 If the wakeup algorithm does not work perfectly at semaphore relases,
 this function will do the waking (see the comment in mutex_exit). This
-function should be called about every 1 second in the server. */
+function should be called about every 1 second in the server.
+
+Note that there's a race condition between this thread and mutex_exit
+changing the lock_word and calling signal_object, so sometimes this finds
+threads to wake up even when nothing has gone wrong. */
 
 void
 sync_arr_wake_threads_if_sema_free(void)
@@ -865,23 +952,33 @@
         sync_cell_t*   	cell;
         ulint           count;
         ulint           i;
-
+	ulint		res_count;
+	
         sync_array_enter(arr);
 
 	i = 0;
 	count = 0;
 
-        while (count < arr->n_reserved) {
+	/* We need to store this to a local variable because it is modified
+	inside the loop */
+
+	res_count = arr->n_reserved;
+	
+        while (count < res_count) {
 
         	cell = sync_array_get_nth_cell(arr, i);
 
-                if (cell->wait_object != NULL) {
+                if (cell->state == SC_RESERVED) {
 
                         count++;
 
                         if (sync_arr_cell_can_wake_up(cell)) {
+				cell->state = SC_WAKING_UP;
+				cell->event_set = TRUE;
+                        	os_event_set(cell->event);
 
-                        	sync_cell_event_set(cell);
+				ut_a(arr->n_reserved > 0);
+				arr->n_reserved--;
                         }
                 }
 
@@ -911,7 +1008,7 @@
 
         	cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
 
-                if (cell->wait_object != NULL
+                if ((cell->state != SC_FREE)
 		    && difftime(time(NULL), cell->reservation_time) > 240) {
 			fputs("InnoDB: Warning: a long semaphore wait:\n",
 				stderr);
@@ -919,7 +1016,7 @@
 			noticed = TRUE;
                 }
 
-                if (cell->wait_object != NULL
+                if ((cell->state != SC_FREE)
 		    && difftime(time(NULL), cell->reservation_time)
 		    > fatal_timeout) {
 			fatal = TRUE;
@@ -965,25 +1062,19 @@
 				mutex */
 {
         sync_cell_t*   	cell;
-        ulint           count;
 	ulint           i;
 
 	fprintf(file,
-		"OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
-						(long) arr->res_count, (long) arr->sg_count);
-	i = 0;
-	count = 0;
-
-        while (count < arr->n_reserved) {
+	"OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
+						(long) arr->res_count,
+						(long) arr->sg_count);
+        for (i = 0; i < arr->n_cells; i++) {
 
         	cell = sync_array_get_nth_cell(arr, i);
 
-                if (cell->wait_object != NULL) {
-                        count++;
+                if (cell->state != SC_FREE) {
 			sync_array_cell_print(file, cell);
                 }
-
-                i++;
        	}
 }
 

--- 1.37/storage/innobase/sync/sync0sync.c	2005-07-22 04:56:23 +04:00
+++ 1.38/storage/innobase/sync/sync0sync.c	2006-03-03 22:34:17 +03:00
@@ -482,7 +482,7 @@
     {
       /* Succeeded! Free the reserved wait cell */
 
-      sync_array_free_cell(sync_primary_wait_array, index);
+      sync_array_free_cell_protected(sync_primary_wait_array, index);
 
 #ifdef UNIV_SYNC_DEBUG
       mutex_set_debug_info(mutex, file_name, line);

--- 1.62/storage/innobase/trx/trx0trx.c	2006-02-02 01:04:02 +03:00
+++ 1.63/storage/innobase/trx/trx0trx.c	2006-03-03 22:34:17 +03:00
@@ -794,7 +794,8 @@
 		in trx sys header if MySQL binlogging is on or the database
 		server is a MySQL replication slave */
 
-		if (trx->mysql_log_file_name) {
+		if (trx->mysql_log_file_name
+				&& trx->mysql_log_file_name[0] != '\0') {
 			trx_sys_update_mysql_binlog_offset(
 					trx->mysql_log_file_name,
 					trx->mysql_log_offset,

--- 1.163/mysql-test/r/innodb.result	2006-02-25 21:35:06 +03:00
+++ 1.164/mysql-test/r/innodb.result	2006-03-03 22:34:14 +03:00
@@ -234,7 +234,7 @@
 commit;
 insert into t1 values (5);
 insert into t1 values (4);
-ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
+ERROR 23000: Duplicate entry '4' for key 1
 commit;
 select n, "after commit" from t1;
 n	after commit
@@ -243,7 +243,7 @@
 set autocommit=1;
 insert into t1 values (6);
 insert into t1 values (4);
-ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
+ERROR 23000: Duplicate entry '4' for key 1
 select n from t1;
 n
 4
@@ -318,7 +318,7 @@
 CREATE TABLE t1 (id char(8) not null primary key, val int not null) engine=innodb;
 insert into t1 values ('pippo', 12);
 insert into t1 values ('pippo', 12);
-ERROR 23000: Duplicate entry 'pippo' for key 'PRIMARY'
+ERROR 23000: Duplicate entry 'pippo' for key 1
 delete from t1;
 delete from t1 where id = 'pippo';
 select * from t1;
@@ -482,9 +482,9 @@
 insert into t1 (ggid,passwd) values ('test1','xxx');
 insert into t1 (ggid,passwd) values ('test2','yyy');
 insert into t1 (ggid,passwd) values ('test2','this will fail');
-ERROR 23000: Duplicate entry 'test2' for key 'ggid'
+ERROR 23000: Duplicate entry 'test2' for key 2
 insert into t1 (ggid,id) values ('this will fail',1);
-ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+ERROR 23000: Duplicate entry '1' for key 1
 select * from t1 where ggid='test1';
 id	ggid	email	passwd
 1	test1		xxx
@@ -497,7 +497,7 @@
 replace into t1 (ggid,id) values ('this will work',1);
 replace into t1 (ggid,passwd) values ('test2','this will work');
 update t1 set id=100,ggid='test2' where id=1;
-ERROR 23000: Duplicate entry 'test2' for key 'ggid'
+ERROR 23000: Duplicate entry 'test2' for key 2
 select * from t1;
 id	ggid	email	passwd
 1	this will work		
@@ -816,7 +816,7 @@
 insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
 LOCK TABLES t1 WRITE;
 insert into t1 values (99,1,2,'D'),(1,1,2,'D');
-ERROR 23000: Duplicate entry '1-1' for key 'PRIMARY'
+ERROR 23000: Duplicate entry '1-1' for key 1
 select id from t1;
 id
 0
@@ -834,7 +834,7 @@
 LOCK TABLES t1 WRITE;
 begin;
 insert into t1 values (99,1,2,'D'),(1,1,2,'D');
-ERROR 23000: Duplicate entry '1-1' for key 'PRIMARY'
+ERROR 23000: Duplicate entry '1-1' for key 1
 select id from t1;
 id
 0
@@ -1457,16 +1457,16 @@
 checksum table t1, t2, t3, t4;
 Table	Checksum
 test.t1	2948697075
-test.t2	2948697075
-test.t3	2948697075
+test.t2	3835700799
+test.t3	3835700799
 test.t4	NULL
 Warnings:
 Error	1146	Table 'test.t4' doesn't exist
 checksum table t1, t2, t3, t4 extended;
 Table	Checksum
-test.t1	2948697075
-test.t2	2948697075
-test.t3	2948697075
+test.t1	3092701434
+test.t2	3835700799
+test.t3	3835700799
 test.t4	NULL
 Warnings:
 Error	1146	Table 'test.t4' doesn't exist
@@ -1589,7 +1589,7 @@
 t2	CREATE TABLE `t2` (
   `id` int(11) NOT NULL auto_increment,
   `id2` int(11) NOT NULL,
-  PRIMARY KEY (`id`),
+  PRIMARY KEY  (`id`),
   KEY `id` (`id`,`id2`),
   CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1622,7 +1622,7 @@
 t2	CREATE TABLE `t2` (
   `a` int(11) NOT NULL auto_increment,
   `b` int(11) default NULL,
-  PRIMARY KEY (`a`),
+  PRIMARY KEY  (`a`),
   UNIQUE KEY `b_2` (`b`),
   KEY `b` (`b`),
   CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
@@ -1634,7 +1634,7 @@
 t2	CREATE TABLE `t2` (
   `a` int(11) NOT NULL auto_increment,
   `b` int(11) default NULL,
-  PRIMARY KEY (`a`),
+  PRIMARY KEY  (`a`),
   UNIQUE KEY `b` (`b`),
   CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`),
   CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
@@ -1783,15 +1783,15 @@
 innodb_sync_spin_loops	20
 show variables like "innodb_thread_concurrency";
 Variable_name	Value
-innodb_thread_concurrency	20
-set global innodb_thread_concurrency=1000;
+innodb_thread_concurrency	0
+set global innodb_thread_concurrency=1001;
 show variables like "innodb_thread_concurrency";
 Variable_name	Value
 innodb_thread_concurrency	1000
 set global innodb_thread_concurrency=0;
 show variables like "innodb_thread_concurrency";
 Variable_name	Value
-innodb_thread_concurrency	1
+innodb_thread_concurrency	0
 set global innodb_thread_concurrency=16;
 show variables like "innodb_thread_concurrency";
 Variable_name	Value
@@ -1964,7 +1964,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ref	v	v	13	const	#	Using where; Using index
 alter table t1 add unique(v);
-ERROR 23000: Duplicate entry '{ ' for key 'v_2'
+ERROR 23000: Duplicate entry '{ ' for key 1
 alter table t1 add key(v);
 select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
 qq
@@ -2324,16 +2324,16 @@
 create table t1 (a char(10), unique (a));
 insert into t1 values ('a   ');
 insert into t1 values ('a ');
-ERROR 23000: Duplicate entry 'a' for key 'a'
+ERROR 23000: Duplicate entry 'a' for key 1
 alter table t1 modify a varchar(10);
 insert into t1 values ('a '),('a  '),('a   '),('a         ');
-ERROR 23000: Duplicate entry 'a ' for key 'a'
+ERROR 23000: Duplicate entry 'a ' for key 1
 insert into t1 values ('a     ');
-ERROR 23000: Duplicate entry 'a     ' for key 'a'
+ERROR 23000: Duplicate entry 'a     ' for key 1
 insert into t1 values ('a          ');
-ERROR 23000: Duplicate entry 'a         ' for key 'a'
+ERROR 23000: Duplicate entry 'a         ' for key 1
 insert into t1 values ('a ');
-ERROR 23000: Duplicate entry 'a ' for key 'a'
+ERROR 23000: Duplicate entry 'a ' for key 1
 update t1 set a='a  ' where a like 'a%';
 select concat(a,'.') from t1;
 concat(a,'.')
@@ -2456,7 +2456,7 @@
 replace into t1 (val) values ('1'),('2');
 replace into t1 (val) values ('1'),('2');
 insert into t1 (val) values ('1'),('2');
-ERROR 23000: Duplicate entry '1' for key 'val'
+ERROR 23000: Duplicate entry '1' for key 2
 select * from t1;
 rowid	val
 3	1
@@ -2466,7 +2466,7 @@
 insert into t1 (val) values (1);
 update t1 set a=2 where a=1;
 insert into t1 (val) values (1);
-ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
+ERROR 23000: Duplicate entry '2' for key 1
 select * from t1;
 a	val
 2	1
@@ -2635,6 +2635,25 @@
 Table	Checksum
 test.t1	2050879373
 drop table t1;
+create table t1 (col1 integer primary key, col2 integer) engine=innodb;
+insert t1 values (1,100);
+create function f1 () returns integer begin
+declare var1 int;
+select col2 into var1 from t1 where col1=1 for update;
+return var1;
+end|
+start transaction;
+select f1();
+f1()
+100
+ update t1 set col2=0 where col1=1;
+select * from t1;
+col1	col2
+1	100
+rollback;
+rollback;
+drop table t1;
+drop function f1;
 create table t1 (
 a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a,
c(2))
 ) character set utf8 engine = innodb;
@@ -2661,6 +2680,32 @@
 insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven');
 insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+a	hex(b)	hex(c)	filler
+1	61626364656667	61626364656667	boo
+4	D0B1	D0B1	eight
+4	5B	5B	five
+4	E880BD	E880BD	four
+4	E880BDD0B1E880BD	E880BDD0B1E880BD	seven
+4	E880BDE880BD	E880BDE880BD	six
+3	71727374757677	71727374757677	three
+2	696A6B696C6D6E	696A6B696C6D6E	two
+select a,hex(b),hex(c),filler from t2 order by filler;
+a	hex(b)	hex(c)	filler
+4	05630563	05630563	email
+4	0563	0563	email
+4	05612020	05612020	email
+4	01FC	01FC	email
+4	0120	0120	email
+4	00640065	00640065	email
+4	00E400E50068	00E400E50068	email
+4	0000E400	0000E400	email
+4	0000563001FC0563	0000563001FC0563	email
+1	0061006200630064006500660067	0061006200630064006500660067	one
+3	0071007200730074007500760077	0071007200730074007500760077	three
+2	0069006A006B0069006C006D006E	0069006A006B0069006C006D006E	two
 drop table t1;
 drop table t2;
 create table t1 (
@@ -2689,6 +2734,32 @@
 insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven');
 insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+a	hex(b)	hex(c)	filler
+1	61626364656667	61626364656667	boo
+4	D0B1	D0B1	eight
+4	5B	5B	five
+4	E880BD	E880BD	four
+4	E880BDD0B1E880BD	E880BDD0B1E880BD	seven
+4	E880BDE880BD	E880BDE880BD	six
+3	71727374757677	71727374757677	three
+2	696A6B696C6D6E	696A6B696C6D6E	two
+select a,hex(b),hex(c),filler from t2 order by filler;
+a	hex(b)	hex(c)	filler
+4	05630563	05630563	email
+4	0563	0563	email
+4	05612020	05612020	email
+4	01FC	01FC	email
+4	0120	0120	email
+4	00640065	00640065	email
+4	00E400E50068	00E400E50068	email
+4	0000E400	0000E400	email
+4	0000563001FC0563	0000563001FC0563	email
+1	0061006200630064006500660067	0061006200630064006500660067	one
+3	0071007200730074007500760077	0071007200730074007500760077	three
+2	0069006A006B0069006C006D006E	0069006A006B0069006C006D006E	two
 drop table t1;
 drop table t2;
 create table t1 (
@@ -2717,6 +2788,32 @@
 insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven');
 insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+a	hex(b)	hex(c)	filler
+1	61626364656667	61626364656667	boo
+4	D0B1	D0B1	eight
+4	5B	5B	five
+4	E880BD	E880BD	four
+4	E880BDD0B1E880BD	E880BDD0B1E880BD	seven
+4	E880BDE880BD	E880BDE880BD	six
+3	71727374757677	71727374757677	three
+2	696A6B696C6D6E	696A6B696C6D6E	two
+select a,hex(b),hex(c),filler from t2 order by filler;
+a	hex(b)	hex(c)	filler
+4	0120	0120	email
+4	01FC	01FC	email
+4	0563	0563	email
+4	0000563001FC0563	0000563001FC0563	email
+4	0000E400	0000E400	email
+4	00640065	00640065	email
+4	00E400E50068	00E400E50068	email
+4	05612020	05612020	email
+4	05630563	05630563	email
+1	0061006200630064006500660067	0061006200630064006500660067	one
+3	0071007200730074007500760077	0071007200730074007500760077	three
+2	0069006A006B0069006C006D006E	0069006A006B0069006C006D006E	two
 drop table t1;
 drop table t2;
 create table t1 (
@@ -2741,9 +2838,92 @@
 insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight');
 insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+a	hex(b)	hex(c)	filler
+1	61626364656667	61626364656667	boo
+4	D0B1	D0B1	eight
+4	5B	5B	five
+4	E880BD	E880BD	four
+3	71727374757677	71727374757677	three
+2	696A6B696C6D6E	696A6B696C6D6E	two
+select a,hex(b),hex(c),filler from t2 order by filler;
+a	hex(b)	hex(c)	filler
+4	0000E400	0000E400	email
+4	00640065	00640065	email
+4	00E400E50068	00E400E50068	email
+4	0120	0120	email
+4	01FC	01FC	email
+4	05612020	05612020	email
+4	0563	0563	email
+1	61626364656667	61626364656667	one
+3	71727374757677	71727374757677	three
+2	696A6B696C6D6E	696A6B696C6D6E	two
 drop table t1;
 drop table t2;
 commit;
+set foreign_key_checks=0;
+create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine =
innodb;
+create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
+ERROR HY000: Can't create table 'test.t1' (errno: 150)
+set foreign_key_checks=1;
+drop table t2;
+set foreign_key_checks=0;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT
CHARSET=utf8;
+ERROR HY000: Can't create table 'test.t2' (errno: 150)
+set foreign_key_checks=1;
+drop table t1;
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
+create table t1(a varchar(10) primary key) engine = innodb;
+alter table t1 modify column a int;
+Got one of the listed errors
+set foreign_key_checks=1;
+drop table t2,t1;
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT
CHARSET=latin1;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+alter table t1 convert to character set utf8;
+set foreign_key_checks=1;
+drop table t2,t1;
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT
CHARSET=latin1;
+create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
+rename table t3 to t1;
+ERROR HY000: Error on rename of './test/t3' to './test/t1' (errno: 150)
+set foreign_key_checks=1;
+drop table t2,t3;
+create table t1(a int primary key) row_format=redundant engine=innodb;
+create table t2(a int primary key,constraint foreign key(a)references t1(a))
row_format=compact engine=innodb;
+create table t3(a int primary key) row_format=compact engine=innodb;
+create table t4(a int primary key,constraint foreign key(a)references t3(a))
row_format=redundant engine=innodb;
+insert into t1 values(1);
+insert into t3 values(1);
+insert into t2 values(2);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`,
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
+insert into t4 values(2);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`,
CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
+insert into t2 values(1);
+insert into t4 values(1);
+update t1 set a=2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
+update t2 set a=2;
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`,
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
+update t3 set a=2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
+update t4 set a=2;
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`,
CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
+truncate t1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
+truncate t3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
+truncate t2;
+truncate t4;
+truncate t1;
+truncate t3;
+drop table t4,t3,t2,t1;
 create table t1 (a varchar(255) character set utf8,
 b varchar(255) character set utf8,
 c varchar(255) character set utf8,
@@ -2757,22 +2937,279 @@
 e varchar(255) character set utf8,
 key (a,b,c,d,e)) engine=innodb;
 ERROR 42000: Specified key was too long; max key length is 3072 bytes
-End of 5.0 tests
+create table t1 (s1 varbinary(2),primary key (s1)) engine=innodb;
+create table t2 (s1 binary(2),primary key (s1)) engine=innodb;
+create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb;
+create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb;
+insert into t1 values (0x41),(0x4120),(0x4100);
+insert into t2 values (0x41),(0x4120),(0x4100);
+ERROR 23000: Duplicate entry 'A' for key 1
+insert into t2 values (0x41),(0x4120);
+insert into t3 values (0x41),(0x4120),(0x4100);
+ERROR 23000: Duplicate entry 'A ' for key 1
+insert into t3 values (0x41),(0x4100);
+insert into t4 values (0x41),(0x4120),(0x4100);
+ERROR 23000: Duplicate entry 'A' for key 1
+insert into t4 values (0x41),(0x4100);
+select hex(s1) from t1;
+hex(s1)
+41
+4100
+4120
+select hex(s1) from t2;
+hex(s1)
+4100
+4120
+select hex(s1) from t3;
+hex(s1)
+4100
+41
+select hex(s1) from t4;
+hex(s1)
+4100
+41
+drop table t1,t2,t3,t4;
+create table t1 (a int primary key,s1 varbinary(3) not null unique) engine=innodb;
+create table t2 (s1 binary(2) not null, constraint c foreign key(s1) references t1(s1) on
update cascade) engine=innodb;
+insert into t1 values(1,0x4100),(2,0x41),(3,0x4120),(4,0x42);
+insert into t2 values(0x42);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`,
CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+insert into t2 values(0x41);
+select hex(s1) from t2;
+hex(s1)
+4100
+update t1 set s1=0x123456 where a=2;
+select hex(s1) from t2;
+hex(s1)
+4100
+update t1 set s1=0x12 where a=1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+update t1 set s1=0x12345678 where a=1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+update t1 set s1=0x123457 where a=1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+update t1 set s1=0x1220 where a=1;
+select hex(s1) from t2;
+hex(s1)
+1220
+update t1 set s1=0x1200 where a=1;
+select hex(s1) from t2;
+hex(s1)
+1200
+update t1 set s1=0x4200 where a=1;
+select hex(s1) from t2;
+hex(s1)
+4200
+delete from t1 where a=1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+delete from t1 where a=2;
+update t2 set s1=0x4120;
+delete from t1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+delete from t1 where a!=3;
+select a,hex(s1) from t1;
+a	hex(s1)
+3	4120
+select hex(s1) from t2;
+hex(s1)
+4120
+drop table t2,t1;
+create table t1 (a int primary key,s1 varchar(2) binary not null unique) engine=innodb;
+create table t2 (s1 char(2) binary not null, constraint c foreign key(s1) references
t1(s1) on update cascade) engine=innodb;
+insert into t1 values(1,0x4100),(2,0x41);
+insert into t2 values(0x41);
+select hex(s1) from t2;
+hex(s1)
+41
+update t1 set s1=0x1234 where a=1;
+select hex(s1) from t2;
+hex(s1)
+41
+update t1 set s1=0x12 where a=2;
+select hex(s1) from t2;
+hex(s1)
+12
+delete from t1 where a=1;
+delete from t1 where a=2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
(`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
+select a,hex(s1) from t1;
+a	hex(s1)
+2	12
+select hex(s1) from t2;
+hex(s1)
+12
+drop table t2,t1;
 CREATE TABLE t1 (
-field1 varchar(8) NOT NULL DEFAULT '',
-field2 varchar(8) NOT NULL DEFAULT '',
-PRIMARY KEY  (field1, field2)
-) ENGINE=InnoDB;
+ind enum('0','1','2') NOT NULL default '0',
+string1 varchar(250) NOT NULL,
+PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 CREATE TABLE t2 (
-field1 varchar(8) NOT NULL DEFAULT '' PRIMARY KEY,
-FOREIGN KEY (field1) REFERENCES t1 (field1)
-ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB;
-INSERT INTO t1 VALUES ('old', 'somevalu');
-INSERT INTO t1 VALUES ('other', 'anyvalue');
-INSERT INTO t2 VALUES ('old');
-INSERT INTO t2 VALUES ('other');
-UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
-ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu',
key 1 would lead to a duplicate entry
-DROP TABLE t2;
-DROP TABLE t1;
+ind enum('0','1','2') NOT NULL default '0',
+string1 varchar(250) NOT NULL,
+PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=ucs2;
+INSERT INTO t1 VALUES ('1', ''),('2', '');
+INSERT INTO t2 VALUES ('1', ''),('2', '');
+SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1;
+hex(ind)	hex(string1)
+31	
+32	
+SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1;
+hex(ind)	hex(string1)
+0031	
+0032	
+drop table t1,t2;
+CREATE TABLE t1 (
+ind set('0','1','2') NOT NULL default '0',
+string1 varchar(250) NOT NULL,
+PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TABLE t2 (
+ind set('0','1','2') NOT NULL default '0',
+string1 varchar(250) NOT NULL,
+PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=ucs2;
+INSERT INTO t1 VALUES ('1', ''),('2', '');
+INSERT INTO t2 VALUES ('1', ''),('2', '');
+SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1;
+hex(ind)	hex(string1)
+31	
+32	
+SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1;
+hex(ind)	hex(string1)
+0031	
+0032	
+drop table t1,t2;
+CREATE TABLE t1 (
+ind bit not null,
+string1 varchar(250) NOT NULL,
+PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TABLE t2 (
+ind bit not null,
+string1 varchar(250) NOT NULL,
+PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=ucs2;
+insert into t1 values(0,''),(1,'');
+insert into t2 values(0,''),(1,'');
+select hex(ind),hex(string1) from t1 order by string1;
+hex(ind)	hex(string1)
+0	
+1	
+select hex(ind),hex(string1) from t2 order by string1;
+hex(ind)	hex(string1)
+0	
+1	
+drop table t1,t2;
+create table t2 (
+a int, b char(10), filler char(10), primary key(a, b(2)) 
+) character set utf8 engine = innodb;
+insert into t2 values (1,'abcdefg','one');
+insert into t2 values (2,'ijkilmn','two');
+insert into t2 values (3, 'qrstuvw','three');
+update t2 set a=5, filler='booo' where a=1;
+drop table t2;
+create table t2 (
+a int, b char(10), filler char(10), primary key(a, b(2)) 
+) character set ucs2 engine = innodb;
+insert into t2 values (1,'abcdefg','one');
+insert into t2 values (2,'ijkilmn','two');
+insert into t2 values (3, 'qrstuvw','three');
+update t2 set a=5, filler='booo' where a=1;
+drop table t2;
+create table t1(a int not null, b char(110),primary key(a,b(100))) engine=innodb default
charset=utf8;
+insert into t1 values(1,'abcdefg'),(2,'defghijk');
+insert into t1 values(6,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1);
+insert into t1 values(7,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2);
+select a,hex(b) from t1 order by b;
+a	hex(b)
+1	61626364656667
+2	6465666768696A6B
+6	D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1
+7	D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2
+update t1 set b = 'three' where a = 6;
+drop table t1;
+create table t1(a int not null, b text(110),primary key(a,b(100))) engine=innodb default
charset=utf8;
+insert into t1 values(1,'abcdefg'),(2,'defghijk');
+insert into t1 values(6,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1);
+insert into t1 values(7,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2);
+select a,hex(b) from t1 order by b;
+a	hex(b)
+1	61626364656667
+2	6465666768696A6B
+6	D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1
+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.130/mysql-test/t/innodb.test	2006-02-25 22:54:29 +03:00
+++ 1.131/mysql-test/t/innodb.test	2006-03-03 22:34:14 +03:00
@@ -1273,7 +1273,7 @@
 
 # Test for innodb_thread_concurrency variable
 show variables like "innodb_thread_concurrency";
-set global innodb_thread_concurrency=1000;
+set global innodb_thread_concurrency=1001;
 show variables like "innodb_thread_concurrency";
 set global innodb_thread_concurrency=0;
 show variables like "innodb_thread_concurrency";
@@ -1576,7 +1576,33 @@
 checksum table t1;
 drop table t1;
 
+#
+# BUG#11238 - in prelocking mode SELECT .. FOR UPDATE is changed to
+# non-blocking SELECT
+#
+create table t1 (col1 integer primary key, col2 integer) engine=innodb;
+insert t1 values (1,100);
+delimiter |;
+create function f1 () returns integer begin
+declare var1 int;
+select col2 into var1 from t1 where col1=1 for update;
+return var1;
+end|
+delimiter ;|
+start transaction;
+select f1();
+connection b;
+send update t1 set col2=0 where col1=1;
+connection default;
+select * from t1;
+connection a;
+rollback;
+connection b;
+reap;
+rollback;
 connection default;
+drop table t1;
+drop function f1;
 disconnect a;
 disconnect b;
 
@@ -1610,6 +1636,10 @@
 insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven');
 insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+select a,hex(b),hex(c),filler from t2 order by filler;
 drop table t1;
 drop table t2;
 
@@ -1639,6 +1669,10 @@
 insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven');
 insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+select a,hex(b),hex(c),filler from t2 order by filler;
 drop table t1;
 drop table t2;
 
@@ -1668,6 +1702,10 @@
 insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven');
 insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+select a,hex(b),hex(c),filler from t2 order by filler;
 drop table t1;
 drop table t2;
 
@@ -1693,10 +1731,99 @@
 insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight');
 insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten');
 insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
+update t1 set filler = 'boo' where a = 1;
+update t2 set filler ='email' where a = 4;
+select a,hex(b),hex(c),filler from t1 order by filler;
+select a,hex(b),hex(c),filler from t2 order by filler;
 drop table t1;
 drop table t2;
 commit;
 
+# tests for bugs #9802 and #13778
+
+# test that FKs between invalid types are not accepted
+
+set foreign_key_checks=0;
+create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine =
innodb;
+-- error 1005
+create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
+set foreign_key_checks=1;
+drop table t2;
+
+# test that FKs between different charsets are not accepted in CREATE even
+# when f_k_c is 0
+
+set foreign_key_checks=0;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+-- error 1005
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT
CHARSET=utf8;
+set foreign_key_checks=1;
+drop table t1;
+
+# test that invalid datatype conversions with ALTER are not allowed
+
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
+create table t1(a varchar(10) primary key) engine = innodb;
+-- error 1025,1025
+alter table t1 modify column a int;
+set foreign_key_checks=1;
+drop table t2,t1;
+
+# test that charset conversions with ALTER are allowed when f_k_c is 0
+
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT
CHARSET=latin1;
+create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
+alter table t1 convert to character set utf8;
+set foreign_key_checks=1;
+drop table t2,t1;
+
+# test that RENAME does not allow invalid charsets when f_k_c is 0
+
+set foreign_key_checks=0;
+create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT
CHARSET=latin1;
+create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
+-- error 1025
+rename table t3 to t1;
+set foreign_key_checks=1;
+drop table t2,t3;
+
+# test that foreign key errors are reported correctly (Bug #15550)
+
+create table t1(a int primary key) row_format=redundant engine=innodb;
+create table t2(a int primary key,constraint foreign key(a)references t1(a))
row_format=compact engine=innodb;
+create table t3(a int primary key) row_format=compact engine=innodb;
+create table t4(a int primary key,constraint foreign key(a)references t3(a))
row_format=redundant engine=innodb;
+
+insert into t1 values(1);
+insert into t3 values(1);
+-- error 1452
+insert into t2 values(2);
+-- error 1452
+insert into t4 values(2);
+insert into t2 values(1);
+insert into t4 values(1);
+-- error 1451
+update t1 set a=2;
+-- error 1452
+update t2 set a=2;
+-- error 1451
+update t3 set a=2;
+-- error 1452
+update t4 set a=2;
+-- error 1451
+truncate t1;
+-- error 1451
+truncate t3;
+truncate t2;
+truncate t4;
+truncate t1;
+truncate t3;
+
+drop table t4,t3,t2,t1;
+
+
 #
 # Test that we can create a large (>1K) key
 #
@@ -1714,33 +1841,268 @@
                  e varchar(255) character set utf8,
                  key (a,b,c,d,e)) engine=innodb;
 
---echo End of 5.0 tests
 
+# test the padding of BINARY types and collations (Bug #14189)
+
+create table t1 (s1 varbinary(2),primary key (s1)) engine=innodb;
+create table t2 (s1 binary(2),primary key (s1)) engine=innodb;
+create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb;
+create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb;
+
+insert into t1 values (0x41),(0x4120),(0x4100);
+-- error 1062
+insert into t2 values (0x41),(0x4120),(0x4100);
+insert into t2 values (0x41),(0x4120);
+-- error 1062
+insert into t3 values (0x41),(0x4120),(0x4100);
+insert into t3 values (0x41),(0x4100);
+-- error 1062
+insert into t4 values (0x41),(0x4120),(0x4100);
+insert into t4 values (0x41),(0x4100);
+select hex(s1) from t1;
+select hex(s1) from t2;
+select hex(s1) from t3;
+select hex(s1) from t4;
+drop table t1,t2,t3,t4;
+
+create table t1 (a int primary key,s1 varbinary(3) not null unique) engine=innodb;
+create table t2 (s1 binary(2) not null, constraint c foreign key(s1) references t1(s1) on
update cascade) engine=innodb;
+
+insert into t1 values(1,0x4100),(2,0x41),(3,0x4120),(4,0x42);
+-- error 1452
+insert into t2 values(0x42);
+insert into t2 values(0x41);
+select hex(s1) from t2;
+update t1 set s1=0x123456 where a=2;
+select hex(s1) from t2;
+-- error 1451
+update t1 set s1=0x12 where a=1;
+-- error 1451
+update t1 set s1=0x12345678 where a=1;
+-- error 1451
+update t1 set s1=0x123457 where a=1;
+update t1 set s1=0x1220 where a=1;
+select hex(s1) from t2;
+update t1 set s1=0x1200 where a=1;
+select hex(s1) from t2;
+update t1 set s1=0x4200 where a=1;
+select hex(s1) from t2;
+-- error 1451
+delete from t1 where a=1;
+delete from t1 where a=2;
+update t2 set s1=0x4120;
+-- error 1451
+delete from t1;
+delete from t1 where a!=3;
+select a,hex(s1) from t1;
+select hex(s1) from t2;
+
+drop table t2,t1;
+
+create table t1 (a int primary key,s1 varchar(2) binary not null unique) engine=innodb;
+create table t2 (s1 char(2) binary not null, constraint c foreign key(s1) references
t1(s1) on update cascade) engine=innodb;
+
+insert into t1 values(1,0x4100),(2,0x41);
+insert into t2 values(0x41);
+select hex(s1) from t2;
+update t1 set s1=0x1234 where a=1;
+select hex(s1) from t2;
+update t1 set s1=0x12 where a=2;
+select hex(s1) from t2;
+delete from t1 where a=1;
+-- error 1451
+delete from t1 where a=2;
+select a,hex(s1) from t1;
+select hex(s1) from t2;
+
+drop table t2,t1;
 #
-# Test that cascading updates leading to duplicate keys give the correct
-# error message (bug #9680)
+# Test cases for bug #15308 Problem of Order with Enum Column in Primary Key
 #
+CREATE TABLE t1 (
+  ind enum('0','1','2') NOT NULL default '0',
+  string1 varchar(250) NOT NULL,
+  PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TABLE t2 (
+  ind enum('0','1','2') NOT NULL default '0',
+  string1 varchar(250) NOT NULL,
+  PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=ucs2;
+
+INSERT INTO t1 VALUES ('1', ''),('2', '');
+INSERT INTO t2 VALUES ('1', ''),('2', '');
+SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1;
+SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1;
+drop table t1,t2;
 
 CREATE TABLE t1 (
-  field1 varchar(8) NOT NULL DEFAULT '',
-  field2 varchar(8) NOT NULL DEFAULT '',
-  PRIMARY KEY  (field1, field2)
-) ENGINE=InnoDB;
+  ind set('0','1','2') NOT NULL default '0',
+  string1 varchar(250) NOT NULL,
+  PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TABLE t2 (
+  ind set('0','1','2') NOT NULL default '0',
+  string1 varchar(250) NOT NULL,
+  PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=ucs2;
+
+INSERT INTO t1 VALUES ('1', ''),('2', '');
+INSERT INTO t2 VALUES ('1', ''),('2', '');
+SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1;
+SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1;
+drop table t1,t2;
 
+CREATE TABLE t1 (
+  ind bit not null,
+  string1 varchar(250) NOT NULL,
+  PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 CREATE TABLE t2 (
-  field1 varchar(8) NOT NULL DEFAULT '' PRIMARY KEY,
-  FOREIGN KEY (field1) REFERENCES t1 (field1)
-    ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB;
+  ind bit not null,
+  string1 varchar(250) NOT NULL,
+  PRIMARY KEY  (ind)
+) ENGINE=InnoDB DEFAULT CHARSET=ucs2;
+insert into t1 values(0,''),(1,'');
+insert into t2 values(0,''),(1,'');
+select hex(ind),hex(string1) from t1 order by string1;
+select hex(ind),hex(string1) from t2 order by string1;
+drop table t1,t2;
+
+# tests for bug #14056 Column prefix index on UTF-8 primary key column causes 'Can't find
record..'
+
+create table t2 (
+  a int, b char(10), filler char(10), primary key(a, b(2)) 
+) character set utf8 engine = innodb;
+
+insert into t2 values (1,'abcdefg','one');
+insert into t2 values (2,'ijkilmn','two');
+insert into t2 values (3, 'qrstuvw','three');
+update t2 set a=5, filler='booo' where a=1;
+drop table t2;
+create table t2 (
+  a int, b char(10), filler char(10), primary key(a, b(2)) 
+) character set ucs2 engine = innodb;
 
-INSERT INTO t1 VALUES ('old', 'somevalu');
-INSERT INTO t1 VALUES ('other', 'anyvalue');
+insert into t2 values (1,'abcdefg','one');
+insert into t2 values (2,'ijkilmn','two');
+insert into t2 values (3, 'qrstuvw','three');
+update t2 set a=5, filler='booo' where a=1;
+drop table t2;
 
-INSERT INTO t2 VALUES ('old');
-INSERT INTO t2 VALUES ('other');
+create table t1(a int not null, b char(110),primary key(a,b(100))) engine=innodb default
charset=utf8;
+insert into t1 values(1,'abcdefg'),(2,'defghijk');
+insert into t1 values(6,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1);
+insert into t1 values(7,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2);
+select a,hex(b) from t1 order by b;
+update t1 set b = 'three' where a = 6;
+drop table t1;
+create table t1(a int not null, b text(110),primary key(a,b(100))) engine=innodb default
charset=utf8;
+insert into t1 values(1,'abcdefg'),(2,'defghijk');
+insert into t1 values(6,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1);
+insert into t1 values(7,_utf8
0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2);
+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;
 
---error ER_FOREIGN_DUPLICATE_KEY
-UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
+#
+# Test case for bug #16229: MySQL/InnoDB uses full explicit table locks in trigger
processing
+#
 
-DROP TABLE t2;
-DROP TABLE t1;
+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.258/sql/ha_innodb.cc	2006-02-26 00:20:52 +03:00
+++ 1.259/sql/ha_innodb.cc	2006-03-03 22:34:15 +03:00
@@ -137,8 +137,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
@@ -166,7 +164,6 @@
 /* Below we have boolean-valued start-up parameters, and their default
 values */
 
-uint	innobase_flush_log_at_trx_commit	= 1;
 ulong	innobase_fast_shutdown			= 1;
 my_bool innobase_log_archive			= FALSE;/* unused */
 my_bool innobase_use_doublewrite    = TRUE;
@@ -187,8 +184,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 */
@@ -235,13 +230,7 @@
   innobase_start_trx_and_assign_read_view,    /* Start Consistent Snapshot */
   innobase_flush_logs,		/* Flush logs */
   innobase_show_status,		/* Show status */
-  NULL,                         /* Partition flags */
-  NULL,                         /* Alter table flags */
-  NULL,                         /* alter_tablespace */
-  NULL,                         /* Fill FILES table */
-  HTON_NO_FLAGS,
-  NULL,                         /* binlog_func */
-  NULL                          /* binlog_log_query */
+  HTON_NO_FLAGS
 };
 
 
@@ -359,7 +348,7 @@
 /*=========================*/
 	trx_t*	trx)	/* in: transaction handle */
 {
-	if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) {
+	if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
 		return;
 	}
@@ -376,7 +365,7 @@
 /*========================*/
 	trx_t*	trx)	/* in: transaction handle */
 {
-	if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) {
+	if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
 		return;
 	}
@@ -468,10 +457,6 @@
 
     		return(HA_ERR_FOUND_DUPP_KEY);
 
-  	} else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) {
-
-		return(HA_ERR_FOREIGN_DUPLICATE_KEY);
-
  	} else if (error == (int) DB_RECORD_NOT_FOUND) {
 
     		return(HA_ERR_NO_ACTIVE_RECORD);
@@ -841,7 +826,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)
 {}
@@ -1010,6 +994,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);
@@ -1367,7 +1356,6 @@
 	srv_log_archive_on = (ulint) innobase_log_archive;
 #endif /* UNIV_LOG_ARCHIVE */
 	srv_log_buffer_size = (ulint) innobase_log_buffer_size;
-	srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;
 
         /* We set srv_pool_size here in units of 1 kB. InnoDB internally
         changes the value so that it becomes the number of database pages. */
@@ -1417,6 +1405,7 @@
 
 	ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
 					my_charset_latin1.number);
+	ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
 
 	/* Store the latin1_swedish_ci character ordering table to InnoDB. For
 	non-latin1_swedish_ci charsets we use the MySQL comparison functions,
@@ -1841,7 +1830,7 @@
 
                 trx->active_trans = 0;
 
-                if (srv_flush_log_at_trx_commit == 0) {
+                if (UNIV_UNLIKELY(srv_flush_log_at_trx_commit == 0)) {
 
                         return(0);
                 }
@@ -2878,8 +2867,6 @@
 	char*		buff_start	= buff;
 	enum_field_types mysql_type;
 	Field*		field;
-	ulint		blob_len;
-	byte*		blob_data;
 	ibool		is_null;
 
   	DBUG_ENTER("store_key_val_for_row");
@@ -2934,14 +2921,18 @@
 			ulint	len;
 			byte*	data;
 			ulint	key_len;
+			ulint	true_len;
 			CHARSET_INFO*	cs;
 			int	error=0;
 
+			key_len = key_part->length;
+
 			if (is_null) {
-				buff += key_part->length + 2;
+				buff += key_len + 2;
 				
 				continue;
 			}
+			cs = field->charset();
 
 			lenlen = (ulint)
 				(((Field_varstring*)field)->length_bytes);
@@ -2951,32 +2942,33 @@
 				+ (ulint)get_field_offset(table, field)),
 				lenlen);
 
-			/* In a column prefix index, we may need to truncate
-			the stored value: */
-		
-			cs = key_part->field->charset();
+			true_len = len;
 
-			if (cs->mbmaxlen > 1 && key_part->length > 0) {
-				key_len = (ulint) cs->cset->well_formed_len(cs, 
-					(const char *) data,
-					(const char *) data + key_part->length,
-					key_part->length / cs->mbmaxlen, 
-					&error);
-			} else {
-				key_len = key_part->length;
+			/* For multi byte character sets we need to calculate
+			the true length of the key */
+
+			if (len > 0 && cs->mbmaxlen > 1) {
+				true_len = (ulint) cs->cset->well_formed_len(cs,
+						(const char *) data,
+						(const char *) data + len,
+						key_len / cs->mbmaxlen, 
+						&error);
 			}
 
-			if (len > key_len) {
-				len = key_len;
+			/* In a column prefix index, we may need to truncate
+			the stored value: */
+
+			if (true_len > key_len) {
+				true_len = key_len;
 			}
 
 			/* The length in a key value is always stored in 2
 			bytes */
 
-			row_mysql_store_true_var_len((byte*)buff, len, 2);
+			row_mysql_store_true_var_len((byte*)buff, true_len, 2);
 			buff += 2;
 
-			memcpy(buff, data, len);
+			memcpy(buff, data, true_len);
 
 			/* Note that we always reserve the maximum possible
 			length of the true VARCHAR in the key value, though
@@ -2984,7 +2976,7 @@
 			actual data. The rest of the space was reset to zero
 			in the bzero() call above. */
 
-			buff += key_part->length;
+			buff += key_len;
 
 		} else if (mysql_type == FIELD_TYPE_TINY_BLOB
 		    || mysql_type == FIELD_TYPE_MEDIUM_BLOB
@@ -2994,58 +2986,66 @@
 			CHARSET_INFO*	cs;
 			ulint		key_len;
 			ulint		len;
+			ulint		true_len;
 			int		error=0;
+			ulint		blob_len;
+			byte*		blob_data;
 
 			ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
 
+			key_len = key_part->length;
+
 		        if (is_null) {
-				buff += key_part->length + 2;
+				buff += key_len + 2;
 				 
 				continue;
 			}
 		    
+			cs = field->charset();
+
 		        blob_data = row_mysql_read_blob_ref(&blob_len,
 				(byte*) (record
 				+ (ulint)get_field_offset(table, field)),
 					(ulint) field->pack_length());
 
+			true_len = blob_len;
+
 			ut_a(get_field_offset(table, field)
 						     == key_part->offset);
 
+			/* For multi byte character sets we need to calculate
+			the true length of the key */
+			
+			if (blob_len > 0 && cs->mbmaxlen > 1) {
+				true_len = (ulint) cs->cset->well_formed_len(cs,
+						(const char *) blob_data,
+						(const char *) blob_data 
+							+ blob_len,
+						key_len / cs->mbmaxlen,
+						&error);
+			}
+
 			/* All indexes on BLOB and TEXT are column prefix
 			indexes, and we may need to truncate the data to be
 			stored in the key value: */
 
-			cs = key_part->field->charset();
-			
-			if (cs->mbmaxlen > 1 && key_part->length > 0) {
-				key_len = (ulint) cs->cset->well_formed_len(cs, 
-					(const char *) blob_data,
-					(const char *) blob_data 
-						+ key_part->length,
-					key_part->length / cs->mbmaxlen,
-					&error);
-			} else {
-				key_len = key_part->length;
-			}
-
-			if (blob_len > key_len) {
-				blob_len = key_len;
+			if (true_len > key_len) {
+				true_len = key_len;
 			}
 
 			/* MySQL reserves 2 bytes for the length and the
 			storage of the number is little-endian */
 
 			innobase_write_to_2_little_endian(
-					(byte*)buff, (ulint)blob_len);
+					(byte*)buff, true_len);
 			buff += 2;
 
-			memcpy(buff, blob_data, blob_len);
+			memcpy(buff, blob_data, true_len);
 
 			/* Note that we always reserve the maximum possible
 			length of the BLOB prefix in the key value. */
 
-			buff += key_part->length;
+			buff += key_len;
 		} else {
 			/* Here we handle all other data types except the
 			true VARCHAR, BLOB and TEXT. Note that the column
@@ -3053,34 +3053,53 @@
 			index. */
 
 			CHARSET_INFO*		cs;
-			ulint			len;
+			ulint			true_len;
+			ulint			key_len;
 			const mysql_byte*	src_start;
 			int			error=0;
+			enum_field_types	real_type;
+
+			key_len = key_part->length;
 
 		        if (is_null) {
-				 buff += key_part->length;
+				 buff += key_len;
 				 
 				 continue;
 			}
 
-			/* In a column prefix index, we may need to truncate
-			the stored value: */
-
-			cs = key_part->field->charset();
 			src_start = record + key_part->offset;
+			real_type = field->real_type();
+			true_len = key_len;
 
-			if (key_part->length > 0 && cs->mbmaxlen > 1) {
-				len = (ulint) cs->cset->well_formed_len(cs, 
-					(const char *) src_start,
-					(const char *) src_start + key_part->length,
-					key_part->length / cs->mbmaxlen, 
-					&error);
-			} else {
-				len = key_part->length;
+			/* Character set for the field is defined only
+			to fields whose type is string and real field
+			type is not enum or set. For these fields check
+			if character set is multi byte. */
+
+			if (real_type != FIELD_TYPE_ENUM 
+				&& real_type != FIELD_TYPE_SET
+				&& ( mysql_type == MYSQL_TYPE_VAR_STRING
+					|| mysql_type == MYSQL_TYPE_STRING)) {
+
+				cs = field->charset();
+
+				/* For multi byte character sets we need to 
+				calculate the true length of the key */
+
+				if (key_len > 0 && cs->mbmaxlen > 1) {
+
+					true_len = (ulint) 
+						cs->cset->well_formed_len(cs,
+							(const char *)src_start,
+							(const char *)src_start 
+								+ key_len,
+							key_len / cs->mbmaxlen,
+							&error);
+				}
 			}
 
-			memcpy(buff, src_start, len);
-			buff+=len;
+			memcpy(buff, src_start, true_len);
+			buff += true_len;
 
 			/* Pad the unused space with spaces. Note that no 
 			padding is ever needed for UCS-2 because in MySQL, 
@@ -3088,10 +3107,10 @@
 			support surrogate pairs, which are needed to represent
 			characters in the range U+10000 to U+10FFFF. */
 
-			if (len < key_part->length) {
-				len = key_part->length - len;
-				memset(buff, ' ', len);
-				buff+=len;
+			if (true_len < key_len) {
+				ulint pad_len = key_len - true_len;
+				memset(buff, ' ', pad_len);
+				buff += pad_len;
 			}
 		}
   	}
@@ -5764,7 +5783,7 @@
 }
 
 /**************************************************************************
-This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
+This is mapped to "ALTER TABLE tablename TYPE=InnoDB", which rebuilds
 the table in MySQL. */
 
 int
@@ -5828,6 +5847,7 @@
 	uint	length			= (uint) strlen(comment);
 	char*				str;
 	row_prebuilt_t*	prebuilt	= (row_prebuilt_t*)innobase_prebuilt;
+	long	flen;
 
 	/* We do not know if MySQL can call this function before calling
 	external_lock(). To be safe, update the thd of the current table
@@ -5847,43 +5867,43 @@
 	trx_search_latch_release_if_reserved(prebuilt->trx);
 	str = NULL;
 
-	if (FILE* file = os_file_create_tmpfile()) {
-		long	flen;
+	/* output the data to a temporary file */
 
-		/* output the data to a temporary file */
-		fprintf(file, "InnoDB free: %lu kB",
+	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
+	rewind(srv_dict_tmpfile);
+
+	fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB",
       		   (ulong) fsp_get_available_space_in_free_extents(
       					prebuilt->table->space));
 
-		dict_print_info_on_foreign_keys(FALSE, file,
+	dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 				prebuilt->trx, prebuilt->table);
-		flen = ftell(file);
-		if (flen < 0) {
-			flen = 0;
-		} else if (length + flen + 3 > 64000) {
-			flen = 64000 - 3 - length;
-		}
-
-		/* allocate buffer for the full string, and
-		read the contents of the temporary file */
-
-		str = my_malloc(length + flen + 3, MYF(0));
-
-		if (str) {
-			char* pos	= str + length;
-			if (length) {
-				memcpy(str, comment, length);
-				*pos++ = ';';
-				*pos++ = ' ';
-			}
-			rewind(file);
-			flen = (uint) fread(pos, 1, flen, file);
-			pos[flen] = 0;
-		}
+	flen = ftell(srv_dict_tmpfile);
+	if (flen < 0) {
+		flen = 0;
+	} else if (length + flen + 3 > 64000) {
+		flen = 64000 - 3 - length;
+	}
 
-		fclose(file);
+	/* allocate buffer for the full string, and
+	read the contents of the temporary file */
+
+	str = my_malloc(length + flen + 3, MYF(0));
+
+	if (str) {
+		char* pos	= str + length;
+		if (length) {
+			memcpy(str, comment, length);
+			*pos++ = ';';
+			*pos++ = ' ';
+		}
+		rewind(srv_dict_tmpfile);
+		flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
+		pos[flen] = 0;
 	}
 
+	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
+
         prebuilt->trx->op_info = (char*)"";
 
   	return(str ? str : (char*) comment);
@@ -5901,6 +5921,7 @@
 {
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
 	char*	str	= 0;
+	long	flen;
 
 	ut_a(prebuilt != NULL);
 
@@ -5910,47 +5931,42 @@
 
 	update_thd(current_thd);
 
-	if (FILE* file = os_file_create_tmpfile()) {
-		long	flen;
+	prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 
-		prebuilt->trx->op_info = (char*)"getting info on foreign keys";
+	/* In case MySQL calls this in the middle of a SELECT query,
+	release possible adaptive hash latch to avoid
+	deadlocks of threads */
 
-		/* In case MySQL calls this in the middle of a SELECT query,
-		release possible adaptive hash latch to avoid
-		deadlocks of threads */
+	trx_search_latch_release_if_reserved(prebuilt->trx);
 
-		trx_search_latch_release_if_reserved(prebuilt->trx);
+	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
+	rewind(srv_dict_tmpfile);
 
-		/* output the data to a temporary file */
-		dict_print_info_on_foreign_keys(TRUE, file,
+	/* output the data to a temporary file */
+	dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
 				prebuilt->trx, prebuilt->table);
-		prebuilt->trx->op_info = (char*)"";
-
-		flen = ftell(file);
-		if (flen < 0) {
-			flen = 0;
-		} else if (flen > 64000 - 1) {
-			flen = 64000 - 1;
-		}
+	prebuilt->trx->op_info = (char*)"";
 
-		/* allocate buffer for the string, and
-		read the contents of the temporary file */
+	flen = ftell(srv_dict_tmpfile);
+	if (flen < 0) {
+		flen = 0;
+	} else if (flen > 64000 - 1) {
+		flen = 64000 - 1;
+	}
 
-		str = my_malloc(flen + 1, MYF(0));
+	/* allocate buffer for the string, and
+	read the contents of the temporary file */
 
-		if (str) {
-			rewind(file);
-			flen = (uint) fread(str, 1, flen, file);
-			str[flen] = 0;
-		}
+	str = my_malloc(flen + 1, MYF(0));
 
-		fclose(file);
-	} else {
-		/* unable to create temporary file */
-          	str = my_strdup(
-"/* Error: cannot display foreign key constraints */", MYF(0));
+	if (str) {
+		rewind(srv_dict_tmpfile);
+		flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
+		str[flen] = 0;
 	}
 
+	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
+
   	return(str);
 }
 
@@ -6380,14 +6396,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)) {
 
@@ -6542,7 +6561,7 @@
 
 int
 innodb_export_status()
-/*======================*/
+/*==================*/
 {
   if (innodb_inited)
     srv_export_innodb_status();
@@ -6875,7 +6894,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;
@@ -6884,7 +6903,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
@@ -6907,26 +6926,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.
+
+		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)
+    		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
@@ -6935,10 +6964,10 @@
 			lock_type = TL_READ;
 		}
 		
- 		lock.type = lock_type;
-  	}
+		lock.type = lock_type;
+	}
 
-  	*to++= &lock;
+	*to++= &lock;
 
 	return(to);
 }

--- 1.117/sql/ha_innodb.h	2006-02-08 13:58:49 +03:00
+++ 1.118/sql/ha_innodb.h	2006-03-03 22:34:15 +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);
@@ -213,12 +210,8 @@
 };
 
 extern SHOW_VAR innodb_status_variables[];
-extern uint innobase_init_flags, innobase_lock_type;
-extern uint innobase_flush_log_at_trx_commit;
-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;
@@ -252,10 +245,9 @@
 extern ulong srv_thread_sleep_delay;
 extern ulong srv_thread_concurrency;
 extern ulong srv_commit_concurrency;
+extern ulong srv_flush_log_at_trx_commit;
 }
 
-extern TYPELIB innobase_lock_typelib;
-
 bool innobase_init(void);
 int innobase_end(ha_panic_function type);
 bool innobase_flush_logs(void);
@@ -321,9 +313,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,

--- 1.13/mysql-test/r/innodb_cache.result	2006-01-23 14:16:57 +03:00
+++ 1.14/mysql-test/r/innodb_cache.result	2006-03-03 22:34:14 +03:00
@@ -121,7 +121,7 @@
 begin;
 insert into t3 VALUES ( NULL, 1, 1, 2 );
 insert into t3 VALUES ( NULL, 1, 1, 2 );
-ERROR 23000: Duplicate entry '1-1' for key 't1_id'
+ERROR 23000: Duplicate entry '1-1' for key 2
 commit;
 select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id
= t2.id and t1.id = 1 order by t1.a asc;
 id	a

--- 1.12/mysql-test/t/innodb_cache.test	2006-01-26 19:54:27 +03:00
+++ 1.13/mysql-test/t/innodb_cache.test	2006-03-03 22:34:15 +03:00
@@ -63,7 +63,6 @@
 #
 # one statement roll back inside transation
 #
-let $save_query_cache_size=`select @@global.query_cache_size`;
 set GLOBAL query_cache_size=1355776;
 CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY
KEY  (id), UNIQUE KEY a (a)) ENGINE=innodb;
 CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY
KEY  (id), UNIQUE KEY b (b)) ENGINE=innodb;
@@ -80,8 +79,5 @@
 commit;
 select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id
= t2.id and t1.id = 1 order by t1.a asc;
 drop table t3,t2,t1;
---disable_query_log
-eval set GLOBAL query_cache_size=$save_query_cache_size;
---enable_query_log
 
 # End of 4.1 tests
Thread
bk commit into 5.1 tree (aivanov:1.2214)Alex Ivanov Notebook3 Mar