List:Commits« Previous MessageNext Message »
From:Alex Ivanov Date:January 23 2006 5:58pm
Subject:bk commit into 5.1 tree (aivanov:1.2068)
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.2068 06/01/23 20:58:17 aivanov@stripped +19 -0
  Merge mysql.com:/home/alexi/dev/mysql-5.0-oldrev
  into  mysql.com:/home/alexi/dev/mysql-5.1-merge

  storage/innobase/trx/trx0trx.c
    1.62 06/01/23 20:58:07 aivanov@stripped +1 -2
    Null merged

  storage/innobase/row/row0sel.c
    1.100 06/01/23 20:58:06 aivanov@stripped +5 -6
    Null merged

  storage/innobase/row/row0mysql.c
    1.120 06/01/23 20:58:06 aivanov@stripped +3 -13
    Null merged

  storage/innobase/row/row0ins.c
    1.75 06/01/23 20:58:06 aivanov@stripped +0 -9
    Null merged

  storage/innobase/os/os0file.c
    1.112 06/01/23 20:58:06 aivanov@stripped +40 -72
    Null merged

  storage/innobase/lock/lock0lock.c
    1.65 06/01/23 20:58:06 aivanov@stripped +0 -70
    Null merged

  storage/innobase/include/row0mysql.h
    1.46 06/01/23 20:58:06 aivanov@stripped +2 -3
    Null merged

  storage/innobase/include/os0file.h
    1.43 06/01/23 20:58:06 aivanov@stripped +2 -3
    Null merged

  storage/innobase/include/data0type.ic
    1.28 06/01/23 20:58:06 aivanov@stripped +15 -24
    Null merged

  storage/innobase/include/data0type.h
    1.23 06/01/23 20:58:06 aivanov@stripped +1 -2
    Null merged

  sql/sql_select.cc
    1.386 06/01/23 20:58:06 aivanov@stripped +0 -0
    Auto merged

  sql/item_cmpfunc.cc
    1.190 06/01/23 20:58:06 aivanov@stripped +0 -0
    Auto merged

  sql/ha_innodb.cc
    1.251 06/01/23 20:58:06 aivanov@stripped +56 -95
    Null merged

  mysql-test/t/ps.test
    1.58 06/01/23 20:58:06 aivanov@stripped +1 -1
    Auto merged

  mysql-test/t/innodb.test
    1.124 06/01/23 20:58:06 aivanov@stripped +1 -180
    Null merged

  mysql-test/r/ps.result
    1.59 06/01/23 20:58:05 aivanov@stripped +1 -1
    Auto merged

  mysql-test/r/innodb.result
    1.155 06/01/23 20:58:05 aivanov@stripped +1 -305
    Null merged

  VC++Files/sql/mysqld.vcproj
    1.8 06/01/23 20:58:05 aivanov@stripped +0 -1
    Hand merged

  storage/innobase/include/lock0lock.h
    1.26 06/01/23 20:40:33 aivanov@stripped +0 -12
    Auto merged

  storage/innobase/row/row0mysql.c
    1.103.12.2 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/row/row0mysql.c -> storage/innobase/row/row0mysql.c

  storage/innobase/row/row0ins.c
    1.65.10.2 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/row/row0ins.c -> storage/innobase/row/row0ins.c

  storage/innobase/os/os0file.c
    1.103.7.3 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/os/os0file.c -> storage/innobase/os/os0file.c

  storage/innobase/lock/lock0lock.c
    1.55.7.2 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/lock/lock0lock.c -> storage/innobase/lock/lock0lock.c

  storage/innobase/include/row0mysql.h
    1.39.5.2 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/include/row0mysql.h -> storage/innobase/include/row0mysql.h

  storage/innobase/include/os0file.h
    1.34.7.3 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/include/os0file.h -> storage/innobase/include/os0file.h

  storage/innobase/include/lock0lock.h
    1.21.3.2 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/include/lock0lock.h -> storage/innobase/include/lock0lock.h

  storage/innobase/include/data0type.ic
    1.24.3.2 06/01/23 20:20:11 aivanov@stripped +0 -0
    Merge rename: innobase/include/data0type.ic -> storage/innobase/include/data0type.ic

  storage/innobase/trx/trx0trx.c
    1.54.8.2 06/01/23 20:20:10 aivanov@stripped +0 -0
    Merge rename: innobase/trx/trx0trx.c -> storage/innobase/trx/trx0trx.c

  storage/innobase/row/row0sel.c
    1.92.5.2 06/01/23 20:20:10 aivanov@stripped +0 -0
    Merge rename: innobase/row/row0sel.c -> storage/innobase/row/row0sel.c

  storage/innobase/include/data0type.h
    1.20.2.2 06/01/23 20:20:10 aivanov@stripped +0 -0
    Merge rename: innobase/include/data0type.h -> storage/innobase/include/data0type.h

# 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:	mysql.creware.com
# Root:	/home/alexi/dev/mysql-5.1-merge/RESYNC

--- 1.189/sql/item_cmpfunc.cc	2006-01-16 16:26:26 +03:00
+++ 1.190/sql/item_cmpfunc.cc	2006-01-23 20:58:06 +03:00
@@ -3059,6 +3059,12 @@
   return FALSE;
 }
 
+void Item_func_like::cleanup()
+{
+  canDoTurboBM= FALSE;
+  Item_bool_func2::cleanup();
+}
+
 #ifdef USE_REGEX
 
 bool

--- 1.385/sql/sql_select.cc	2006-01-16 16:26:27 +03:00
+++ 1.386/sql/sql_select.cc	2006-01-23 20:58:06 +03:00
@@ -2956,6 +2956,56 @@
 
 
 /*
+  Add to KEY_FIELD array all 'ref' access candidates within nested join
+
+  SYNPOSIS
+    add_key_fields_for_nj()
+      nested_join_table  IN     Nested join pseudo-table to process
+      end                INOUT  End of the key field array
+      and_level          INOUT  And-level
+
+  DESCRIPTION
+    This function populates KEY_FIELD array with entries generated from the 
+    ON condition of the given nested join, and does the same for nested joins 
+    contained within this nested join.
+
+  NOTES
+    We can add accesses to the tables that are direct children of this nested 
+    join (1), and are not inner tables w.r.t their neighbours (2).
+    
+    Example for #1 (outer brackets pair denotes nested join this function is 
+    invoked for):
+     ... LEFT JOIN (t1 LEFT JOIN (t2 ... ) ) ON cond
+    Example for #2:
+     ... LEFT JOIN (t1 LEFT JOIN t2 ) ON cond
+    In examples 1-2 for condition cond, we can add 'ref' access candidates to 
+    t1 only.
+    Example #3:
+     ... LEFT JOIN (t1, t2 LEFT JOIN t3 ON inner_cond) ON cond
+    Here we can add 'ref' access candidates for t1 and t2, but not for t3.
+*/
+
+static void add_key_fields_for_nj(TABLE_LIST *nested_join_table,
+                                  KEY_FIELD **end, uint *and_level)
+{
+  List_iterator<TABLE_LIST> li(nested_join_table->nested_join->join_list);
+  table_map tables= 0;
+  TABLE_LIST *table;
+  DBUG_ASSERT(nested_join_table->nested_join);
+
+  while ((table= li++))
+  {
+    if (table->nested_join)
+      add_key_fields_for_nj(table, end, and_level);
+    else
+      if (!table->on_expr)
+        tables |= table->table->map;
+  }
+  add_key_fields(end, and_level, nested_join_table->on_expr, tables);
+}
+
+
+/*
   Update keyuse array with all possible keys we can use to fetch rows
   
   SYNOPSIS
@@ -3019,23 +3069,21 @@
       into account as well.
     */ 
     if (*join_tab[i].on_expr_ref)
-    {
       add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref,
 		     join_tab[i].table->map);
-    }
-    else 
+  }
+
+  /* Process ON conditions for the nested joins */
+  {
+    List_iterator<TABLE_LIST> li(*join_tab->join->join_list);
+    TABLE_LIST *table;
+    while ((table= li++))
     {
-      TABLE_LIST *tab= join_tab[i].table->pos_in_table_list;
-      TABLE_LIST *embedding= tab->embedding;
-      if (embedding)
-      {
-        NESTED_JOIN *nested_join= embedding->nested_join;
-        if (nested_join->join_list.head() == tab)
-          add_key_fields(&end, &and_level, embedding->on_expr,
-                         nested_join->used_tables);
-      }
+      if (table->nested_join)
+	add_key_fields_for_nj(table, &end, &and_level);
     }
   }
+
   /* fill keyuse with found key parts */
   for ( ; field != end ; field++)
     add_key_part(keyuse,field);

--- 1.7/VC++Files/sql/mysqld.vcproj	2006-01-14 00:09:38 +03:00
+++ 1.8/VC++Files/sql/mysqld.vcproj	2006-01-23 20:58:05 +03:00
@@ -3925,7 +3925,81 @@
 			</FileConfiguration>
 		</File>
 		<File
-			RelativePath="..\storage\myisammrg\myrg_rnext_same.c">
+			RelativePath="my_user.c">
+			<FileConfiguration
+				Name="classic nt|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Max|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Max nt|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="nt|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="pro nt|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Debug|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="0"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="pro|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="classic|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Release|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions=""/>
+			</FileConfiguration>
+		</File>
+		<File
 			<FileConfiguration
 				Name="classic nt|Win32">
 				<Tool

--- 1.20.2.1/innobase/include/data0type.h	2006-01-16 14:03:54 +03:00
+++ 1.23/storage/innobase/include/data0type.h	2006-01-23 20:58:06 +03:00
@@ -13,7 +13,6 @@
 
 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;
@@ -312,7 +311,7 @@
 /*===============*/
 				/* out: padding character code, or
 				ULINT_UNDEFINED if no padding specified */
-	const dtype_t*	type);	/* in: type */
+	dtype_t*	type);	/* in: type */
 /***************************************************************************
 Returns the size of a fixed size data type, 0 if not a fixed size type. */
 UNIV_INLINE

--- 1.24.3.1/innobase/include/data0type.ic	2006-01-16 14:03:55 +03:00
+++ 1.28/storage/innobase/include/data0type.ic	2006-01-23 20:58:06 +03:00
@@ -188,35 +188,26 @@
 /*===============*/
 				/* out: padding character code, or
 				ULINT_UNDEFINED if no padding specified */
-	const dtype_t*	type)	/* in: type */
+	dtype_t*	type)	/* in: type */
 {
-	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:
+	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)) {
+
 		/* Space is the padding character for all char and binary
 	        strings, and starting from 5.0.3, also for TEXT strings. */
 
-		return(0x20);
-	case DATA_BLOB:
-		if ((type->prtype & DATA_BINARY_TYPE) == 0) {
-			return(0x20);
-		}
-		/* Fall through */
-	default:
-		/* No padding specified */
-		return(ULINT_UNDEFINED);
+		return((ulint)' ');
 	}
+
+	/* No padding specified */
+
+	return(ULINT_UNDEFINED);
 }
 
 /**************************************************************************

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

--- 1.39.5.1/innobase/include/row0mysql.h	2006-01-16 14:03:55 +03:00
+++ 1.46/storage/innobase/include/row0mysql.h	2006-01-23 20:58:06 +03:00
@@ -250,9 +250,8 @@
 really were set. This function removes a newly set lock under prebuilt->pcur,
 and also under prebuilt->clust_pcur. Currently, this is only used and tested
 in the case of an UPDATE or a DELETE statement, where the row lock is of the
-LOCK_X or LOCK_S type. 
-
-Thus, this implements a 'mini-rollback' that releases the latest record 
+LOCK_X type.
+Thus, this implements a 'mini-rollback' that releases the latest record
 locks we set. */
 
 int
@@ -613,6 +612,31 @@
 					that was decided in ha_innodb.cc,
 					::store_lock(), ::external_lock(),
 					etc. */
+	ulint		row_read_type;	/* ROW_READ_WITH_LOCKS if row locks
+					should be the obtained for records
+					under an UPDATE or DELETE cursor.
+					If innodb_locks_unsafe_for_binlog
+					is TRUE, this can be set to
+					ROW_READ_TRY_SEMI_CONSISTENT, so that
+					if the row under an UPDATE or DELETE
+					cursor was locked by another
+					transaction, InnoDB will resort
+					to reading the last committed value
+					('semi-consistent read').  Then,
+					this field will be set to
+					ROW_READ_DID_SEMI_CONSISTENT to
+					indicate that.  If the row does not
+					match the WHERE condition, MySQL will
+					invoke handler::unlock_row() to
+					clear the flag back to
+					ROW_READ_TRY_SEMI_CONSISTENT and
+					to simply skip the row.  If
+					the row matches, the next call to
+					row_search_for_mysql() will lock
+					the row.
+					This eliminates lock waits in some
+					cases; note that this breaks
+					serializability. */
 	ulint		mysql_prefix_len;/* byte offset of the end of
 					the last requested column */
 	ulint		mysql_row_len;	/* length in bytes of a row in the
@@ -657,6 +681,11 @@
 /* Values for hint_need_to_fetch_extra_cols */
 #define ROW_RETRIEVE_PRIMARY_KEY	1
 #define ROW_RETRIEVE_ALL_COLS		2
+
+/* Values for row_read_type */
+#define ROW_READ_WITH_LOCKS		0
+#define ROW_READ_TRY_SEMI_CONSISTENT	1
+#define ROW_READ_DID_SEMI_CONSISTENT	2
 
 
 #ifndef UNIV_NONINL

--- 1.55.7.1/innobase/lock/lock0lock.c	2006-01-16 14:03:55 +03:00
+++ 1.65/storage/innobase/lock/lock0lock.c	2006-01-23 20:58:06 +03:00
@@ -1705,7 +1705,7 @@
 lock_t*
 lock_rec_create(
 /*============*/
-				/* out: created lock, NULL if out of memory */
+				/* out: created lock */
 	ulint		type_mode,/* in: lock mode and wait flag, type is
 				ignored and replaced by LOCK_REC */
 	rec_t*		rec,	/* in: record on page */
@@ -1746,11 +1746,6 @@
 	n_bytes = 1 + n_bits / 8;
 
 	lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
-	
-	if (UNIV_UNLIKELY(lock == NULL)) {
-
-		return(NULL);
-	}
 
 	UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
 
@@ -1886,8 +1881,7 @@
 lock_t*
 lock_rec_add_to_queue(
 /*==================*/
-				/* out: lock where the bit was set, NULL if out
-				of memory */
+				/* out: lock where the bit was set */
 	ulint		type_mode,/* in: lock mode, wait, gap etc. flags;
 				type is ignored and replaced by LOCK_REC */
 	rec_t*		rec,	/* in: record on page */
@@ -3405,8 +3399,7 @@
 lock_t*
 lock_table_create(
 /*==============*/
-				/* out, own: new lock object, or NULL if
-				out of memory */
+				/* out, own: new lock object */
 	dict_table_t*	table,	/* in: database table in dictionary cache */
 	ulint		type_mode,/* in: lock mode possibly ORed with
 				LOCK_WAIT */
@@ -3432,11 +3425,6 @@
 		lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t));
 	}
 
-	if (lock == NULL) {
-
-		return(NULL);
-	}
-
 	UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
 
 	lock->type_mode = type_mode | LOCK_TABLE;
@@ -3773,9 +3761,8 @@
 	rec_t*	rec,		/* in: record */
 	ulint	lock_mode)	/* in: LOCK_S or LOCK_X */
 {
-	lock_t*	lock;
-	lock_t*	release_lock	= NULL;
-	ulint	heap_no;
+	lock_t* lock;
+	ulint heap_no;
 
 	ut_ad(trx && rec);
 
@@ -3785,23 +3772,21 @@
 
 	lock = lock_rec_get_first(rec);
 
-	/* Find the last lock with the same lock_mode and transaction
-	from the record. */
+	/* Remove the record lock */
 
 	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 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 {
+	if (UNIV_UNLIKELY(lock == NULL)) {
 		mutex_exit(&kernel_mutex);
 		ut_print_timestamp(stderr);
 		fprintf(stderr,

--- 1.103.7.2/innobase/os/os0file.c	2006-01-16 14:03:55 +03:00
+++ 1.112/storage/innobase/os/os0file.c	2006-01-23 20:58:06 +03:00
@@ -160,12 +160,15 @@
 
 ibool	os_has_said_disk_full	= FALSE;
 
-/* The mutex protecting the following counts of pending I/O operations */
+/* The mutex protecting the following counts of pending pread and pwrite
+operations */
 static os_mutex_t os_file_count_mutex;
 ulint	os_file_n_pending_preads  = 0;
 ulint	os_file_n_pending_pwrites = 0;
-ulint	os_n_pending_writes = 0;
-ulint	os_n_pending_reads = 0;
+
+/* These are not protected by any mutex */
+ulint os_n_pending_writes = 0;
+ulint os_n_pending_reads = 0;
 
 /***************************************************************************
 Gets the operating system version. Currently works only on Windows. */
@@ -311,8 +314,6 @@
 		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);
 	}
@@ -362,8 +363,7 @@
 
 		return(TRUE);
 
-	} else if (err == OS_FILE_ALREADY_EXISTS
-			|| err == OS_FILE_PATH_ERROR) {
+	} else if (err == OS_FILE_ALREADY_EXISTS) {
 
 		return(FALSE);
 	} else {
@@ -467,8 +467,7 @@
 
 		return(TRUE);
 
-	} else if (err == OS_FILE_ALREADY_EXISTS
-			|| err == OS_FILE_PATH_ERROR) {
+	} else if (err == OS_FILE_ALREADY_EXISTS) {
 
 		return(FALSE);
 	} else {
@@ -1906,14 +1905,12 @@
 #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);
@@ -1923,10 +1920,6 @@
 	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;
 	
@@ -1935,17 +1928,15 @@
 	ret_offset = lseek(file, offs, SEEK_SET);
 
 	if (ret_offset < 0) {
-		ret = -1;
-	} else {
-		ret = read(file, buf, (ssize_t)n);
+		os_mutex_exit(os_file_seek_mutexes[i]);
+
+		return(-1);
 	}
+	
+	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
@@ -1990,14 +1981,12 @@
 #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
@@ -2019,10 +2008,6 @@
 	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;
 	
@@ -2031,9 +2016,9 @@
 	ret_offset = lseek(file, offs, SEEK_SET);
 
 	if (ret_offset < 0) {
-		ret = -1;
+		os_mutex_exit(os_file_seek_mutexes[i]);
 
-		goto func_exit;
+		return(-1);
 	}
 	
 	ret = write(file, buf, (ssize_t)n);
@@ -2051,13 +2036,8 @@
 	}
 # 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
@@ -2102,13 +2082,9 @@
 	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);
@@ -2117,21 +2093,17 @@
 
 		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);
 	}		
@@ -2142,8 +2114,12 @@
 	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);
@@ -2217,10 +2193,6 @@
 	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;
 	
@@ -2232,21 +2204,17 @@
 
 		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);
 	}		
@@ -2257,8 +2225,12 @@
 	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);
@@ -2338,10 +2310,6 @@
 	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;
 	
@@ -2353,10 +2321,6 @@
 
 		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,
@@ -2371,8 +2335,12 @@
 		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. */
 
@@ -2384,10 +2352,6 @@
 
 	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);
@@ -2438,7 +2402,11 @@
 #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.65.10.1/innobase/row/row0ins.c	2006-01-16 14:03:55 +03:00
+++ 1.75/storage/innobase/row/row0ins.c	2006-01-23 20:58:06 +03:00
@@ -549,15 +549,6 @@
 					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);
@@ -597,21 +588,20 @@
 	trx_t*		trx,		/* in: transaction */
 	dict_foreign_t*	foreign)	/* in: foreign key constraint */
 {
-	mutex_enter(&srv_misc_tmpfile_mutex);
-	rewind(srv_misc_tmpfile);
+		
+	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);
+
+		trx_set_detailed_error_from_file(trx, 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);
+		fclose(tf);
 	} else {
-		trx_set_detailed_error(trx, "temp file operation failed");
+		trx_set_detailed_error(trx, "temp file creation failed");
 	}
-
-	mutex_exit(&srv_misc_tmpfile_mutex);
 }
 
 /*************************************************************************
@@ -719,7 +709,7 @@
 	}
 
 	if (rec) {
-		rec_print(ef, rec, foreign->referenced_index);
+		rec_print(ef, rec, foreign->foreign_index);
 	}
 	putc('\n', ef);
 

--- 1.103.12.1/innobase/row/row0mysql.c	2006-01-16 14:03:55 +03:00
+++ 1.120/storage/innobase/row/row0mysql.c	2006-01-23 20:58:06 +03:00
@@ -626,6 +626,8 @@
 	prebuilt->select_lock_type = LOCK_NONE;
 	prebuilt->stored_select_lock_type = 99999999;
 
+	prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
+
 	prebuilt->sel_graph = NULL;
 
 	prebuilt->search_tuple = dtuple_create(heap,
@@ -1436,9 +1438,8 @@
 really were set. This function removes a newly set lock under prebuilt->pcur,
 and also under prebuilt->clust_pcur. Currently, this is only used and tested
 in the case of an UPDATE or a DELETE statement, where the row lock is of the
-LOCK_X or LOCK_S type. 
-
-Thus, this implements a 'mini-rollback' that releases the latest record 
+LOCK_X type.
+Thus, this implements a 'mini-rollback' that releases the latest record
 locks we set. */
 
 int
@@ -1475,14 +1476,7 @@
 
 	index = btr_pcur_get_btr_cur(pcur)->index;
 
-	if (UNIV_UNLIKELY(index == NULL)) {
-		fprintf(stderr,
-"InnoDB: Error: Index is not set for persistent cursor.\n");
-		ut_print_buf(stderr, (const byte*)pcur, sizeof(btr_pcur_t));
-		ut_error;
-	}
-
-	if (trx_new_rec_locks_contain(trx, index)) {
+	if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
 
 		mtr_start(&mtr);
 			
@@ -2132,7 +2126,7 @@
 
 	if (err == DB_SUCCESS) {
 		/* Check that also referencing constraints are ok */
-		err = dict_load_foreigns(name, TRUE);
+		err = dict_load_foreigns(name, trx->check_foreigns);
 	}
 
 	if (err != DB_SUCCESS) {
@@ -3490,7 +3484,8 @@
 	const char*	name)	/* in: table name in the form
 				'database/tablename' */
 {
-	return(strstr(name, "/#sql") != NULL);
+	/* return(strstr(name, "/#sql") != NULL); */
+	return(strstr(name, "/@0023sql") != NULL);
 }
 
 /*************************************************************************
@@ -3590,8 +3585,7 @@
 	mem_heap_t*	heap			= NULL;
 	const char**	constraints_to_drop	= NULL;
 	ulint		n_constraints_to_drop	= 0;
-	ibool           recovering_temp_table   = FALSE;
-	ibool		old_is_tmp, new_is_tmp;
+        ibool           recovering_temp_table   = FALSE;
 	ulint		len;
 	ulint		i;
         ibool		success;
@@ -3631,9 +3625,6 @@
 	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;
@@ -3680,7 +3671,7 @@
 	len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
 		+ ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
 
-	if (new_is_tmp) {
+	if (row_is_mysql_tmp_table_name(new_name)) {
 		db_name_len = dict_get_db_name_len(old_name) + 1;
 
 		/* MySQL is doing an ALTER TABLE command and it renames the
@@ -3833,7 +3824,7 @@
 		the table is stored in a single-table tablespace */
 
 		success = dict_table_rename_in_cache(table, new_name,
-				!new_is_tmp);
+				!row_is_mysql_tmp_table_name(new_name));
 		if (!success) {
 			trx->error_state = DB_SUCCESS;
 			trx_general_rollback_for_mysql(trx, FALSE, NULL);
@@ -3850,16 +3841,19 @@
 			goto funct_exit;
 		}
 
-		/* 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);
+		err = dict_load_foreigns(new_name, trx->check_foreigns);
 
-		if (err != DB_SUCCESS) {
-			ut_print_timestamp(stderr);
+		if (row_is_mysql_tmp_table_name(old_name)) {
+
+			/* 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 (old_is_tmp) {
+			if (err != DB_SUCCESS) {
+	    			ut_print_timestamp(stderr);
 				fputs("  InnoDB: Error: in ALTER TABLE ",
 					stderr);
 				ut_print_name(stderr, trx, new_name);
@@ -3867,23 +3861,36 @@
 	"InnoDB: has or is referenced in foreign key constraints\n"
 	"InnoDB: which are not compatible with the new table definition.\n",
 					stderr);
-			} else {
+
+				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);
+
 				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,
+     
+				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;
+						
+				trx->error_state = DB_SUCCESS;
+				trx_general_rollback_for_mysql(trx, FALSE,
+									NULL);
+				trx->error_state = DB_SUCCESS;
+			}
 		}
 	}
 funct_exit:	

--- 1.92.5.1/innobase/row/row0sel.c	2006-01-16 14:03:55 +03:00
+++ 1.100/storage/innobase/row/row0sel.c	2006-01-23 20:58:06 +03:00
@@ -536,6 +536,41 @@
 }
 
 /*************************************************************************
+Builds the last committed version of a clustered index record for a
+semi-consistent read. */
+static
+ulint
+row_sel_build_committed_vers_for_mysql(
+/*===================================*/
+					/* out: DB_SUCCESS or error code */
+	dict_index_t*	clust_index,	/* in: clustered index */
+	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct */
+	rec_t*		rec,		/* in: record in a clustered index */
+	ulint**		offsets,	/* in/out: offsets returned by
+					rec_get_offsets(rec, clust_index) */
+	mem_heap_t**	offset_heap,	/* in/out: memory heap from which
+					the offsets are allocated */
+	rec_t**		old_vers,	/* out: old version, or NULL if the
+					record does not exist in the view:
+					i.e., it was freshly inserted
+					afterwards */
+	mtr_t*		mtr)		/* in: mtr */
+{
+	ulint	err;
+
+	if (prebuilt->old_vers_heap) {
+		mem_heap_empty(prebuilt->old_vers_heap);
+	} else {
+		prebuilt->old_vers_heap = mem_heap_create(200);
+	}
+	
+	err = row_vers_build_for_semi_consistent_read(rec, mtr, clust_index,
+					offsets, offset_heap,
+					prebuilt->old_vers_heap, old_vers);
+	return(err);
+}
+
+/*************************************************************************
 Tests the conditions which determine when the index segment we are searching
 through has been exhausted. */
 UNIV_INLINE
@@ -2771,8 +2806,8 @@
 func_exit:
 	*out_rec = clust_rec;
 
-	if (prebuilt->select_lock_type != LOCK_NONE) {
-		/* We may use the cursor in unlock: store its position */
+	if (prebuilt->select_lock_type == LOCK_X) {
+		/* We may use the cursor in update: store its position */
 		
 		btr_pcur_store_position(prebuilt->clust_pcur, mtr);
 	}
@@ -3066,7 +3101,6 @@
 	rec_t*		rec;
 	rec_t*		result_rec;
 	rec_t*		clust_rec;
-	rec_t*		old_vers;
 	ulint		err				= DB_SUCCESS;
 	ibool		unique_search			= FALSE;
 	ibool		unique_search_from_clust_index	= FALSE;
@@ -3077,6 +3111,11 @@
 					locking SELECT, and the isolation
 					level is <= TRX_ISO_READ_COMMITTED,
 					then this is set to FALSE */
+	ibool		did_semi_consistent_read	= FALSE;
+					/* if the returned record was locked
+					and we did a semi-consistent read
+					(fetch the newest committed version),
+					then this is set to TRUE */
 #ifdef UNIV_SEARCH_DEBUG
 	ulint		cnt				= 0;
 #endif /* UNIV_SEARCH_DEBUG */
@@ -3163,7 +3202,7 @@
 		trx->search_latch_timeout = BTR_SEA_TIMEOUT;
 	}
 	
-	/* Reset the new record lock info if we srv_locks_unsafe_for_binlog
+	/* Reset the new record lock info if srv_locks_unsafe_for_binlog
 	is set. Then we are able to remove the record locks set here on an
 	individual row. */
 
@@ -3431,9 +3470,28 @@
 	clust_index = dict_table_get_first_index(index->table);
 
 	if (UNIV_LIKELY(direction != 0)) {
-		if (!sel_restore_position_for_mysql(&same_user_rec,
-						BTR_SEARCH_LEAF,
-						pcur, moves_up, &mtr)) {
+		ibool	need_to_process = sel_restore_position_for_mysql(
+				&same_user_rec, BTR_SEARCH_LEAF,
+				pcur, moves_up, &mtr);
+
+		if (UNIV_UNLIKELY(need_to_process)) {
+			if (UNIV_UNLIKELY(prebuilt->row_read_type
+					== ROW_READ_DID_SEMI_CONSISTENT)) {
+				/* We did a semi-consistent read,
+				but the record was removed in
+				the meantime. */
+				prebuilt->row_read_type
+					= ROW_READ_TRY_SEMI_CONSISTENT;
+			}
+		} else if (UNIV_LIKELY(prebuilt->row_read_type
+			   != ROW_READ_DID_SEMI_CONSISTENT)) {
+
+			/* The cursor was positioned on the record
+			that we returned previously.  If we need
+			to repeat a semi-consistent read as a
+			pessimistic locking read, the record
+			cannot be skipped. */
+
 			goto next_rec;
 		}
 
@@ -3751,7 +3809,64 @@
 					prebuilt->select_lock_type,
 					lock_type, thr);
 
-		if (err != DB_SUCCESS) {
+		switch (err) {
+			rec_t*	old_vers;
+		case DB_SUCCESS:
+			break;
+		case DB_LOCK_WAIT:
+			if (UNIV_LIKELY(prebuilt->row_read_type
+			    != ROW_READ_TRY_SEMI_CONSISTENT)
+			    || index != clust_index) {
+
+				goto lock_wait_or_error;
+			}
+
+			/* The following call returns 'offsets'
+			associated with 'old_vers' */
+			err = row_sel_build_committed_vers_for_mysql(
+					clust_index, prebuilt, rec,
+					&offsets, &heap,
+					&old_vers, &mtr);
+
+			if (err != DB_SUCCESS) {
+
+				goto lock_wait_or_error;
+			}
+
+			mutex_enter(&kernel_mutex);
+			if (trx->was_chosen_as_deadlock_victim) {
+				mutex_exit(&kernel_mutex);
+
+				goto lock_wait_or_error;
+			}
+			if (UNIV_LIKELY(trx->wait_lock != NULL)) {
+				lock_cancel_waiting_and_release(
+						trx->wait_lock);
+				trx_reset_new_rec_lock_info(trx);
+			} else {
+				mutex_exit(&kernel_mutex);
+
+				/* The lock was granted while we were
+				searching for the last committed version.
+				Do a normal locking read. */
+
+				offsets = rec_get_offsets(rec, index, offsets,
+						ULINT_UNDEFINED, &heap);
+				err = DB_SUCCESS;
+				break;
+			}
+			mutex_exit(&kernel_mutex);
+
+			if (old_vers == NULL) {
+				/* The row was not yet committed */
+
+				goto next_rec;
+			}
+
+			did_semi_consistent_read = TRUE;
+			rec = old_vers;
+			break;
+		default:
 
 			goto lock_wait_or_error;
 		}
@@ -3775,6 +3890,7 @@
                             && !lock_clust_rec_cons_read_sees(rec, index,
 						offsets, trx->read_view)) {
 
+				rec_t*	old_vers;
 				/* The following call returns 'offsets'
 				associated with 'old_vers' */
 				err = row_sel_build_prev_vers_for_mysql(
@@ -3821,14 +3937,13 @@
 		/* The record is delete-marked: we can skip it */
 
 		if (srv_locks_unsafe_for_binlog
-	    	    && prebuilt->select_lock_type != LOCK_NONE) {
+	    	    && prebuilt->select_lock_type != LOCK_NONE
+		    && !did_semi_consistent_read) {
 
 			/* No need to keep a lock on a delete-marked record
 			if we do not want to use next-key locking. */
 
 			row_unlock_for_mysql(prebuilt, TRUE);
-			
-			trx_reset_new_rec_lock_info(trx);
 		}
 		
 		goto next_rec;
@@ -3882,8 +3997,6 @@
 				locking. */
 
 				row_unlock_for_mysql(prebuilt, TRUE);
-			
-				trx_reset_new_rec_lock_info(trx);
 			}
 
 			goto next_rec;
@@ -3972,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'. 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. */
+	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. */
 
 	if (!unique_search_from_clust_index
 	    || prebuilt->select_lock_type != LOCK_NONE
@@ -3990,6 +4103,19 @@
 	goto normal_return;
 
 next_rec:
+	/* Reset the old and new "did semi-consistent read" flags. */
+	if (UNIV_UNLIKELY(prebuilt->row_read_type
+			== ROW_READ_DID_SEMI_CONSISTENT)) {
+		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
+	}
+	did_semi_consistent_read = FALSE;
+
+	if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog)
+	    && prebuilt->select_lock_type != LOCK_NONE) {
+
+		trx_reset_new_rec_lock_info(trx);
+	}
+
 	/*-------------------------------------------------------------*/
 	/* PHASE 5: Move the cursor to the next index record */
 
@@ -4042,8 +4168,14 @@
 	goto rec_loop;
 
 lock_wait_or_error:
-	/*-------------------------------------------------------------*/
+	/* Reset the old and new "did semi-consistent read" flags. */
+	if (UNIV_UNLIKELY(prebuilt->row_read_type
+				== ROW_READ_DID_SEMI_CONSISTENT)) {
+		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
+	}
+	did_semi_consistent_read = FALSE;
 
+	/*-------------------------------------------------------------*/
 	btr_pcur_store_position(pcur, &mtr);
 
 	mtr_commit(&mtr);
@@ -4125,6 +4257,20 @@
 	trx->op_info = "";
 	if (UNIV_LIKELY_NULL(heap)) {
 		mem_heap_free(heap);
+	}
+
+	/* Set or reset the "did semi-consistent read" flag on return.
+	The flag did_semi_consistent_read is set if and only if
+	the record being returned was fetched with a semi-consistent read. */
+	ut_ad(prebuilt->row_read_type != ROW_READ_WITH_LOCKS
+		|| !did_semi_consistent_read);
+
+	if (UNIV_UNLIKELY(prebuilt->row_read_type != ROW_READ_WITH_LOCKS)) {
+		if (UNIV_UNLIKELY(did_semi_consistent_read)) {
+			prebuilt->row_read_type = ROW_READ_DID_SEMI_CONSISTENT;
+		} else {
+			prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
+		}
 	}
 	return(err);
 }

--- 1.54.8.1/innobase/trx/trx0trx.c	2006-01-16 14:03:55 +03:00
+++ 1.62/storage/innobase/trx/trx0trx.c	2006-01-23 20:58:07 +03:00
@@ -794,8 +794,7 @@
 		in trx sys header if MySQL binlogging is on or the database
 		server is a MySQL replication slave */
 
-		if (trx->mysql_log_file_name
-				&& trx->mysql_log_file_name[0] != '\0') {
+		if (trx->mysql_log_file_name) {
 			trx_sys_update_mysql_binlog_offset(
 					trx->mysql_log_file_name,
 					trx->mysql_log_offset,

--- 1.58/mysql-test/r/ps.result	2006-01-10 21:50:16 +03:00
+++ 1.59/mysql-test/r/ps.result	2006-01-23 20:58:05 +03:00
@@ -250,7 +250,7 @@
 1234
 1234
 set names latin1;
+execute `ü`;
 1234
 1234
 set names default;
@@ -825,6 +825,40 @@
 drop table t1;
 set names default;
 deallocate prepare stmt;
+create table t1 (
+word_id mediumint(8) unsigned not null default '0',
+formatted varchar(20) not null default ''
+);
+insert into t1 values
+(80,'pendant'), (475,'pretendants'), (989,'tendances'),
+(1019,'cependant'),(1022,'abondance'),(1205,'independants'),
+(13,'lessiver'),(25,'lambiner'),(46,'situer'),(71,'terminer'),
+(82,'decrocher');
+select count(*) from t1 where formatted like '%NDAN%';
+count(*)
+6
+select count(*) from t1 where formatted like '%ER';
+count(*)
+5
+prepare stmt from "select count(*) from t1 where formatted like ?";
+set @like="%NDAN%";
+execute stmt using @like;
+count(*)
+6
+set @like="%ER";
+execute stmt using @like;
+count(*)
+5
+set @like="%NDAN%";
+execute stmt using @like;
+count(*)
+6
+set @like="%ER";
+execute stmt using @like;
+count(*)
+5
+deallocate prepare stmt;
+drop table t1;
 create table t1 (id int);
 prepare ins_call from "insert into t1 (id) values (1)";
 execute ins_call;

--- 1.57/mysql-test/t/ps.test	2005-12-26 10:16:29 +03:00
+++ 1.58/mysql-test/t/ps.test	2006-01-23 20:58:06 +03:00
@@ -256,7 +256,7 @@
 prepare `ü` from 'select 1234';
 execute `ü` ;
 set names latin1;
+execute `ü`;
 set names default;
 
 
@@ -869,6 +869,36 @@
 # Cleanup
 set names default;
 deallocate prepare stmt;
+
+#
+# A test case for Bug#12734 "prepared statement may return incorrect result
+# set for a select SQL request": test that canDoTurboBM is reset for each
+# execute of a prepared statement.
+#
+create table t1 (
+  word_id mediumint(8) unsigned not null default '0',
+  formatted varchar(20) not null default ''
+);
+
+insert into t1 values
+  (80,'pendant'), (475,'pretendants'), (989,'tendances'),
+  (1019,'cependant'),(1022,'abondance'),(1205,'independants'),
+  (13,'lessiver'),(25,'lambiner'),(46,'situer'),(71,'terminer'),
+  (82,'decrocher');
+
+select count(*) from t1 where formatted like '%NDAN%';
+select count(*) from t1 where formatted like '%ER';
+prepare stmt from "select count(*) from t1 where formatted like ?";
+set @like="%NDAN%";
+execute stmt using @like;
+set @like="%ER";
+execute stmt using @like;
+set @like="%NDAN%";
+execute stmt using @like;
+set @like="%ER";
+execute stmt using @like;
+deallocate prepare stmt;
+drop table t1;
 
 # End of 4.1 tests
 
Thread
bk commit into 5.1 tree (aivanov:1.2068)Alex Ivanov23 Jan