List:Commits« Previous MessageNext Message »
From:Chad MILLER Date:September 28 2006 1:20pm
Subject:bk commit into 5.1 tree (cmiller:1.2334)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of cmiller. When cmiller 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@stripped, 2006-09-28 07:20:50-04:00, cmiller@stripped +9 -0
  Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.0-maint
  into  zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-maint
  MERGE: 1.1810.1697.175

  extra/yassl/src/Makefile.am@stripped, 2006-09-28 07:20:46-04:00, cmiller@stripped
+0 -0
    Auto merged
    MERGE: 1.10.1.2

  extra/yassl/taocrypt/benchmark/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.2.1.1

  extra/yassl/taocrypt/src/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.14.1.1

  extra/yassl/taocrypt/test/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.2.1.1

  extra/yassl/testsuite/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.3.1.3

  mysql-test/mysql-test-run.pl@stripped, 2006-09-28 07:20:47-04:00,
cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.30.1.92

  mysql-test/r/strict.result@stripped, 2006-09-28 07:20:47-04:00, cmiller@stripped
+0 -0
    Auto merged
    MERGE: 1.25.1.5

  sql/Makefile.am@stripped, 2006-09-28 07:20:47-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.103.1.23

  storage/innobase/handler/ha_innodb.cc@stripped, 2006-09-28 07:20:47-04:00,
cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.202.26.2

  storage/innobase/handler/ha_innodb.cc@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
    Merge rename: sql/ha_innodb.cc -> storage/innobase/handler/ha_innodb.cc

# 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:	cmiller
# Host:	zippy.cornsilk.net
# Root:	/home/cmiller/work/mysql/mysql-5.1-maint/RESYNC

--- 1.202.26.1/sql/ha_innodb.cc	2006-09-28 07:20:56 -04:00
+++ 1.302/storage/innobase/handler/ha_innodb.cc	2006-09-28 07:20:56 -04:00
@@ -31,10 +31,10 @@ have disables the InnoDB inlining in thi
 #pragma implementation				// gcc: Class implementation
 #endif
 
-#include "mysql_priv.h"
-#include "slave.h"
+#include <mysql_priv.h>
+
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
 
-#ifdef HAVE_INNOBASE_DB
 #include <m_ctype.h>
 #include <hash.h>
 #include <myisampack.h>
@@ -111,28 +111,30 @@ typedef byte	mysql_byte;
 
 /* Include necessary InnoDB headers */
 extern "C" {
-#include "../innobase/include/univ.i"
-#include "../innobase/include/os0file.h"
-#include "../innobase/include/os0thread.h"
-#include "../innobase/include/srv0start.h"
-#include "../innobase/include/srv0srv.h"
-#include "../innobase/include/trx0roll.h"
-#include "../innobase/include/trx0trx.h"
-#include "../innobase/include/trx0sys.h"
-#include "../innobase/include/mtr0mtr.h"
-#include "../innobase/include/row0ins.h"
-#include "../innobase/include/row0mysql.h"
-#include "../innobase/include/row0sel.h"
-#include "../innobase/include/row0upd.h"
-#include "../innobase/include/log0log.h"
-#include "../innobase/include/lock0lock.h"
-#include "../innobase/include/dict0crea.h"
-#include "../innobase/include/btr0cur.h"
-#include "../innobase/include/btr0btr.h"
-#include "../innobase/include/fsp0fsp.h"
-#include "../innobase/include/sync0sync.h"
-#include "../innobase/include/fil0fil.h"
-#include "../innobase/include/trx0xa.h"
+#include "../storage/innobase/include/univ.i"
+#include "../storage/innobase/include/os0file.h"
+#include "../storage/innobase/include/os0thread.h"
+#include "../storage/innobase/include/srv0start.h"
+#include "../storage/innobase/include/srv0srv.h"
+#include "../storage/innobase/include/trx0roll.h"
+#include "../storage/innobase/include/trx0trx.h"
+#include "../storage/innobase/include/trx0sys.h"
+#include "../storage/innobase/include/mtr0mtr.h"
+#include "../storage/innobase/include/row0ins.h"
+#include "../storage/innobase/include/row0mysql.h"
+#include "../storage/innobase/include/row0sel.h"
+#include "../storage/innobase/include/row0upd.h"
+#include "../storage/innobase/include/log0log.h"
+#include "../storage/innobase/include/lock0lock.h"
+#include "../storage/innobase/include/dict0crea.h"
+#include "../storage/innobase/include/btr0cur.h"
+#include "../storage/innobase/include/btr0btr.h"
+#include "../storage/innobase/include/fsp0fsp.h"
+#include "../storage/innobase/include/sync0sync.h"
+#include "../storage/innobase/include/fil0fil.h"
+#include "../storage/innobase/include/trx0xa.h"
+#include "../storage/innobase/include/thr0loc.h"
+#include "../storage/innobase/include/ha_prototypes.h"
 }
 
 #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
@@ -201,30 +203,18 @@ static int innobase_rollback(THD* thd, b
 static int innobase_rollback_to_savepoint(THD* thd, void *savepoint);
 static int innobase_savepoint(THD* thd, void *savepoint);
 static int innobase_release_savepoint(THD* thd, void *savepoint);
+static handler *innobase_create_handler(TABLE_SHARE *table,
+                                        MEM_ROOT *mem_root);
+
+static const char innobase_hton_name[]= "InnoDB";
+
+handlerton *innobase_hton;
+
+static handler *innobase_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
+{
+  return new (mem_root) ha_innobase(table);
+}
 
-handlerton innobase_hton = {
-  "InnoDB",
-  SHOW_OPTION_YES,
-  "Supports transactions, row-level locking, and foreign keys",
-  DB_TYPE_INNODB,
-  innobase_init,
-  0,				/* slot */
-  sizeof(trx_named_savept_t),	/* savepoint size. TODO: use it */
-  innobase_close_connection,
-  innobase_savepoint,
-  innobase_rollback_to_savepoint,
-  innobase_release_savepoint,
-  innobase_commit,		/* commit */
-  innobase_rollback,		/* rollback */
-  innobase_xa_prepare,		/* prepare */
-  innobase_xa_recover,		/* recover */
-  innobase_commit_by_xid,	/* commit_by_xid */
-  innobase_rollback_by_xid,     /* rollback_by_xid */
-  innobase_create_cursor_view,
-  innobase_set_cursor_view,
-  innobase_close_cursor_view,
-  HTON_NO_FLAGS
-};
 
 /*********************************************************************
 Commits a transaction in an InnoDB database. */
@@ -234,7 +224,7 @@ innobase_commit_low(
 /*================*/
 	trx_t*	trx);	/* in: transaction handle */
 
-struct show_var_st innodb_status_variables[]= {
+SHOW_VAR innodb_status_variables[]= {
   {"buffer_pool_pages_data",
   (char*) &export_vars.innodb_buffer_pool_pages_data,     SHOW_LONG},
   {"buffer_pool_pages_dirty",
@@ -321,7 +311,8 @@ struct show_var_st innodb_status_variabl
   (char*) &export_vars.innodb_rows_read,                  SHOW_LONG},
   {"rows_updated",
   (char*) &export_vars.innodb_rows_updated,               SHOW_LONG},
-  {NullS, NullS, SHOW_LONG}};
+  {NullS, NullS, SHOW_LONG}
+};
 
 /* General functions */
 
@@ -386,7 +377,7 @@ Call this function when mysqld passes co
 avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
 documentation, see handler.cc. */
 
-void
+int
 innobase_release_temporary_latches(
 /*===============================*/
         THD *thd)
@@ -395,14 +386,15 @@ innobase_release_temporary_latches(
 
 	if (!innodb_inited) {
 
-		return;
+		return 0;
 	}
 
-	trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*) thd->ha_data[innobase_hton->slot];
 
 	if (trx) {
         	innobase_release_stat_resources(trx);
 	}
+	return 0;
 }
 
 /************************************************************************
@@ -442,6 +434,10 @@ convert_error_code_to_mysql(
 
     		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);
@@ -613,8 +609,7 @@ innobase_mysql_print_thd(
 		/* Points to buf or dyn_str. */
 		char*	str = buf;
 
-		if (max_query_len == 0)
-		{
+		if (max_query_len == 0) {
 			/* ADDITIONAL SAFETY: the default is to print at
 			   most 300 chars to reduce the probability of a
 			   seg fault if there is a race in
@@ -626,8 +621,7 @@ innobase_mysql_print_thd(
 
 		len = min(thd->query_length, max_query_len);
 
-		if (len > (sizeof(buf) - 1))
-		{
+		if (len > (sizeof(buf) - 1)) {
 			dyn_str = my_malloc(len + 1, MYF(0));
 			str = dyn_str;
 		}
@@ -638,8 +632,7 @@ innobase_mysql_print_thd(
 		putc('\n', f);
 		fwrite(str, 1, len, f);
 
-		if (dyn_str)
-		{
+		if (dyn_str) {
 			my_free(dyn_str, MYF(0));
 		}
 	}
@@ -676,6 +669,61 @@ innobase_get_cset_width(
 }
 
 /**********************************************************************
+Converts an identifier to a table name.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+void
+innobase_convert_from_table_id(
+/*===========================*/
+	char*		to,	/* out: converted identifier */
+	const char*	from,	/* in: identifier to convert */
+	ulint		len)	/* in: length of 'to', in bytes */
+{
+	uint	errors;
+
+	strconvert(current_thd->charset(), from,
+		   &my_charset_filename, to, len, &errors);
+}
+
+/**********************************************************************
+Converts an identifier to UTF-8.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+void
+innobase_convert_from_id(
+/*=====================*/
+	char*		to,	/* out: converted identifier */
+	const char*	from,	/* in: identifier to convert */
+	ulint		len)	/* in: length of 'to', in bytes */
+{
+	uint	errors;
+
+	strconvert(current_thd->charset(), from,
+		   system_charset_info, to, len, &errors);
+}
+
+/**********************************************************************
+Removes the filename encoding of a table or database name.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+void
+innobase_convert_from_filename(
+/*===========================*/
+	char*		s)	/* in: identifier; out: decoded identifier */
+{
+	uint	errors;
+
+	strconvert(&my_charset_filename, s,
+		   system_charset_info, s, strlen(s), &errors);
+}
+
+/**********************************************************************
 Compares NUL-terminated UTF-8 strings case insensitively.
 
 NOTE that the exact prototype of this function has to be in
@@ -705,6 +753,21 @@ innobase_casedn_str(
 	my_casedn_str(system_charset_info, a);
 }
 
+/**************************************************************************
+Determines the connection character set.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+struct charset_info_st*
+innobase_get_charset(
+/*=================*/
+				/* out: connection character set */
+	void*	mysql_thd)	/* in: MySQL thread handle */
+{
+	return(((THD*) mysql_thd)->charset());
+}
+
 /*************************************************************************
 Creates a temporary file. */
 extern "C"
@@ -751,6 +814,25 @@ innobase_mysql_tmpfile(void)
 }
 
 /*************************************************************************
+Wrapper around MySQL's copy_and_convert function, see it for
+documentation. */
+extern "C"
+ulint
+innobase_convert_string(
+/*====================*/
+	void*		to,
+	ulint		to_length,
+	CHARSET_INFO*	to_cs,
+	const void*	from,
+	ulint		from_length,
+	CHARSET_INFO*	from_cs,
+	uint*		errors)
+{
+	return(copy_and_convert((char*)to, to_length, to_cs,
+		       (const char*)from, from_length, from_cs, errors));
+}
+
+/*************************************************************************
 Gets the InnoDB transaction handle for a MySQL handler object, creates
 an InnoDB transaction struct if the corresponding MySQL thread struct still
 lacks one. */
@@ -765,7 +847,7 @@ check_trx_exists(
 
 	ut_ad(thd == current_thd);
 
-        trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*) thd->ha_data[innobase_hton->slot];
 
 	if (trx == NULL) {
 	        DBUG_ASSERT(thd != NULL);
@@ -779,10 +861,10 @@ check_trx_exists(
 		CPU time */
 		trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
 
-                thd->ha_data[innobase_hton.slot] = trx;
+		thd->ha_data[innobase_hton->slot] = trx;
 	} else {
 		if (trx->magic_n != TRX_MAGIC_N) {
-			mem_analyze_corruption((byte*)trx);
+			mem_analyze_corruption(trx);
 
 			ut_a(0);
 		}
@@ -807,15 +889,15 @@ check_trx_exists(
 /*************************************************************************
 Construct ha_innobase handler. */
 
-ha_innobase::ha_innobase(TABLE *table_arg)
-  :handler(&innobase_hton, table_arg),
+ha_innobase::ha_innobase(TABLE_SHARE *table_arg)
+  :handler(innobase_hton, table_arg),
   int_table_flags(HA_REC_NOT_IN_SEQ |
                   HA_NULL_IN_KEY |
                   HA_CAN_INDEX_BLOBS |
                   HA_CAN_SQL_HANDLER |
-                  HA_NOT_EXACT_COUNT |
+		  HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
                   HA_PRIMARY_KEY_IN_READ_INDEX |
-                  HA_CAN_GEOMETRY |
+		  HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
                   HA_TABLE_SCAN_ON_INDEX),
   start_of_scan(0),
   num_write_row(0)
@@ -859,7 +941,7 @@ innobase_register_stmt(
 	THD*	thd)	/* in: MySQL thd (connection) object */
 {
         /* Register the statement */
-        trans_register_ha(thd, FALSE, &innobase_hton);
+	trans_register_ha(thd, FALSE, innobase_hton);
 }
 
 /*************************************************************************
@@ -883,7 +965,7 @@ innobase_register_trx_and_stmt(
         if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
               /* No autocommit mode, register for a transaction */
-              trans_register_ha(thd, TRUE, &innobase_hton);
+		trans_register_ha(thd, TRUE, innobase_hton);
         }
 }
 
@@ -1084,23 +1166,70 @@ innobase_invalidate_query_cache(
 }
 
 /*********************************************************************
-Get the quote character to be used in SQL identifiers.
+Display an SQL identifier.
 This definition must match the one in innobase/ut/ut0ut.c! */
 extern "C"
-int
-mysql_get_identifier_quote_char(
-/*============================*/
-				/* out: quote character to be
-				used in SQL identifiers; EOF if none */
+void
+innobase_print_identifier(
+/*======================*/
+	FILE*		f,	/* in: output stream */
 	trx_t*		trx,	/* in: transaction */
+	ibool		table_id,/* in: TRUE=print a table name,
+				FALSE=print other identifier */
 	const char*	name,	/* in: name to print */
 	ulint		namelen)/* in: length of name */
 {
+	const char*	s	= name;
+	char*		qname	= NULL;
+	int		q;
+
+	if (table_id) {
+		/* Decode the table name.  The filename_to_tablename()
+		function expects a NUL-terminated string.  The input and
+		output strings buffers must not be shared.  The function
+		only produces more output when the name contains other
+		characters than [0-9A-Z_a-z]. */
+		char*	temp_name = my_malloc(namelen + 1, MYF(MY_WME));
+		uint	qnamelen = namelen
+				+ (1 + sizeof srv_mysql50_table_name_prefix);
+
+		if (temp_name) {
+			qname = my_malloc(qnamelen, MYF(MY_WME));
+			if (qname) {
+				memcpy(temp_name, name, namelen);
+				temp_name[namelen] = 0;
+				s = qname;
+				namelen = filename_to_tablename(temp_name,
+						qname, qnamelen);
+			}
+			my_free(temp_name, MYF(0));
+		}
+	}
+
 	if (!trx || !trx->mysql_thd) {
-		return(EOF);
+
+		q = '"';
+	} else {
+		q = get_quote_char_for_identifier((THD*) trx->mysql_thd,
+						s, (int) namelen);
 	}
-	return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
-						name, (int) namelen));
+
+	if (q == EOF) {
+		fwrite(s, 1, namelen, f);
+	} else {
+		const char*	e = s + namelen;
+		putc(q, f);
+		while (s < e) {
+			int	c = *s++;
+			if (c == q) {
+				putc(c, f);
+			}
+			putc(c, f);
+		}
+		putc(q, f);
+	}
+
+	my_free(qname, MYF(MY_ALLOW_ZERO_PTR));
 }
 
 /**************************************************************************
@@ -1199,10 +1328,9 @@ ha_innobase::init_table_handle_for_HANDL
 /*************************************************************************
 Opens an InnoDB database. */
 
-bool
-innobase_init(void)
+int
+innobase_init(void *p)
 /*===============*/
-			/* out: &innobase_hton, or NULL on error */
 {
 	static char	current_dir[3];		/* Set if using current lib */
 	int		err;
@@ -1210,12 +1338,56 @@ innobase_init(void)
 	char 	        *default_path;
 
   	DBUG_ENTER("innobase_init");
+        innobase_hton= (handlerton *)p;
+
+        innobase_hton->state=have_innodb;
+        innobase_hton->db_type= DB_TYPE_INNODB;
+        innobase_hton->savepoint_offset=sizeof(trx_named_savept_t);
+        innobase_hton->close_connection=innobase_close_connection;
+        innobase_hton->savepoint_set=innobase_savepoint;
+        innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
+        innobase_hton->savepoint_release=innobase_release_savepoint;
+        innobase_hton->commit=innobase_commit;
+        innobase_hton->rollback=innobase_rollback;
+        innobase_hton->prepare=innobase_xa_prepare;
+        innobase_hton->recover=innobase_xa_recover;
+        innobase_hton->commit_by_xid=innobase_commit_by_xid;
+        innobase_hton->rollback_by_xid=innobase_rollback_by_xid;
+        innobase_hton->create_cursor_read_view=innobase_create_cursor_view;
+        innobase_hton->set_cursor_read_view=innobase_set_cursor_view;
+        innobase_hton->close_cursor_read_view=innobase_close_cursor_view;
+        innobase_hton->create=innobase_create_handler;
+        innobase_hton->drop_database=innobase_drop_database;
+        innobase_hton->panic=innobase_end;
+       
innobase_hton->start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
+        innobase_hton->flush_logs=innobase_flush_logs;
+        innobase_hton->show_status=innobase_show_status;
+        innobase_hton->flags=HTON_NO_FLAGS;
+        innobase_hton->release_temporary_latches=innobase_release_temporary_latches;
 
          if (have_innodb != SHOW_OPTION_YES)
-           goto error;
+	   DBUG_RETURN(0); // nothing else to do
 
 	ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
 
+#ifdef UNIV_DEBUG
+	static const char	test_filename[] = "-@";
+	char			test_tablename[sizeof test_filename
+				+ sizeof srv_mysql50_table_name_prefix];
+	if ((sizeof test_tablename) - 1
+			!= filename_to_tablename(test_filename, test_tablename,
+			sizeof test_tablename)
+			|| strncmp(test_tablename,
+			srv_mysql50_table_name_prefix,
+			sizeof srv_mysql50_table_name_prefix)
+			|| strcmp(test_tablename
+			+ sizeof srv_mysql50_table_name_prefix,
+			test_filename)) {
+		sql_print_error("tablename encoding has been changed");
+		goto error;
+	}
+#endif /* UNIV_DEBUG */
+
 	/* Check that values don't overflow on 32-bit systems. */
 	if (sizeof(ulint) == 4) {
 		if (innobase_buffer_pool_size > UINT_MAX32) {
@@ -1431,21 +1603,6 @@ innobase_init(void)
         pthread_cond_init(&commit_cond, NULL);
 	innodb_inited= 1;
 
-	/* If this is a replication slave and we needed to do a crash recovery,
-	set the master binlog position to what InnoDB internally knew about
-	how far we got transactions durable inside InnoDB. There is a
-	problem here: if the user used also MyISAM tables, InnoDB might not
-	know the right position for them.
-
-	THIS DOES NOT WORK CURRENTLY because replication seems to initialize
-	glob_mi also after innobase_init. */
-
-/*	if (trx_sys_mysql_master_log_pos != -1) {
-		ut_memcpy(glob_mi.log_file_name, trx_sys_mysql_master_log_name,
-				1 + ut_strlen(trx_sys_mysql_master_log_name));
-		glob_mi.pos = trx_sys_mysql_master_log_pos;
-	}
-*/
 	DBUG_RETURN(FALSE);
 error:
         have_innodb= SHOW_OPTION_DISABLED;	// If we couldn't use handler
@@ -1455,8 +1612,8 @@ error:
 /***********************************************************************
 Closes an InnoDB database. */
 
-bool
-innobase_end(void)
+int
+innobase_end(ha_panic_function type)
 /*==============*/
 				/* out: TRUE if error */
 {
@@ -1520,19 +1677,6 @@ innobase_commit_low(
                 return;
         }
 
-#ifdef HAVE_REPLICATION
-        THD *thd=current_thd;
-
-        if (thd && thd->slave_thread) {
-                /* Update the replication position info inside InnoDB */
-
-                trx->mysql_master_log_file_name
-                                        = active_mi->rli.group_master_log_name;
-                trx->mysql_master_log_pos = ((ib_longlong)
-                                active_mi->rli.future_group_master_log_pos);
-        }
-#endif /* HAVE_REPLICATION */
-
 	trx_commit_for_mysql(trx);
 }
 
@@ -1632,8 +1776,8 @@ innobase_commit(
         if (trx->active_trans == 0
 	    && trx->conc_state != TRX_NOT_STARTED) {
 
-	  sql_print_error("trx->active_trans == 0, but trx->conc_state != "
-			  "TRX_NOT_STARTED");
+		sql_print_error("trx->active_trans == 0, but"
+			" trx->conc_state != TRX_NOT_STARTED");
 	}
         if (all
 	    || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
@@ -1642,22 +1786,24 @@ innobase_commit(
 		this is an SQL statement end and autocommit is on */
 
                 /* We need current binlog position for ibbackup to work.
-                Note, the position is current because of prepare_commit_mutex */
+		Note, the position is current because of
+		prepare_commit_mutex */
 retry:
-                if (srv_commit_concurrency > 0)
-                {
+		if (srv_commit_concurrency > 0) {
                   pthread_mutex_lock(&commit_cond_m);
                   commit_threads++;
-                  if (commit_threads > srv_commit_concurrency)
-                  {
+
+			if (commit_threads > srv_commit_concurrency) {
                     commit_threads--;
-                    pthread_cond_wait(&commit_cond, &commit_cond_m);
+				pthread_cond_wait(&commit_cond,
+					&commit_cond_m);
                     pthread_mutex_unlock(&commit_cond_m);
                     goto retry;
                   }
-                  else
+			else {
                     pthread_mutex_unlock(&commit_cond_m);
                 }
+		}
 
                 trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
                 trx->mysql_log_offset =
@@ -1665,8 +1811,7 @@ retry:
 
 		innobase_commit_low(trx);
 
-                if (srv_commit_concurrency > 0)
-                {
+		if (srv_commit_concurrency > 0) {
                   pthread_mutex_lock(&commit_cond_m);
                   commit_threads--;
                   pthread_cond_signal(&commit_cond);
@@ -1795,7 +1940,7 @@ innobase_commit_complete(
 {
 	trx_t*	trx;
 
-        trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*) thd->ha_data[innobase_hton->slot];
 
         if (trx && trx->active_trans) {
 
@@ -2014,27 +2159,30 @@ innobase_close_connection(
 {
 	trx_t*	trx;
 
-	trx = (trx_t*)thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*)thd->ha_data[innobase_hton->slot];
 
 	ut_a(trx);
 
         if (trx->active_trans == 0
 	    && trx->conc_state != TRX_NOT_STARTED) {
 
-	  sql_print_error("trx->active_trans == 0, but trx->conc_state != "
-			  "TRX_NOT_STARTED");
+		sql_print_error("trx->active_trans == 0, but"
+			" trx->conc_state != TRX_NOT_STARTED");
 	}
 
 
 	if (trx->conc_state != TRX_NOT_STARTED &&
-            global_system_variables.log_warnings)
-          sql_print_warning("MySQL is closing a connection that has an active "
+		global_system_variables.log_warnings) {
+		sql_print_warning(
+			"MySQL is closing a connection that has an active "
                             "InnoDB transaction.  %lu row modifications will "
                             "roll back.",
                             (ulong)trx->undo_no.low);
+	}
 
 	innobase_rollback_trx(trx);
 
+	thr_local_free(trx->mysql_thread_id);
         trx_free_for_mysql(trx);
 
 	return(0);
@@ -2055,7 +2203,7 @@ ha_innobase::get_row_type() const
 	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 
 	if (prebuilt && prebuilt->table) {
-		if (prebuilt->table->comp) {
+		if (dict_table_is_comp_noninline(prebuilt->table)) {
 			return(ROW_TYPE_COMPACT);
 		} else {
 			return(ROW_TYPE_REDUNDANT);
@@ -2179,8 +2327,8 @@ ha_innobase::open(
 
 	/* Get pointer to a table object in InnoDB dictionary cache */
 
-	ib_table = dict_table_get_and_increment_handle_count(
-				      		     norm_name, NULL);
+	ib_table = dict_table_get_and_increment_handle_count(norm_name);
+
  	if (NULL == ib_table) {
 	        ut_print_timestamp(stderr);
 		sql_print_error("Cannot find table %s from the internal data "
@@ -2190,7 +2338,7 @@ ha_innobase::open(
 				"have forgotten\nto delete the corresponding "
 				".frm files of InnoDB tables, or you\n"
 				"have moved .frm files to another database?\n"
-				"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
+				"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
 				"how you can resolve the problem.\n",
 				norm_name);
 	        free_share(share);
@@ -2207,7 +2355,7 @@ ha_innobase::open(
 				"Have you deleted the .ibd file from the "
 				"database directory under\nthe MySQL datadir, "
 				"or have you used DISCARD TABLESPACE?\n"
-				"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
+				"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
 				"how you can resolve the problem.\n",
 				norm_name);
 	        free_share(share);
@@ -2276,13 +2424,14 @@ ha_innobase::open(
 		and it will never be updated anyway. */
 
 		if (key_used_on_scan != MAX_KEY) {
-		  sql_print_warning("Table %s key_used_on_scan is %lu even "
+			sql_print_warning(
+				"Table %s key_used_on_scan is %lu even "
 				    "though there is no primary key inside "
 				    "InnoDB.", name, (ulong) key_used_on_scan);
 		}
 	}
 
-	block_size = 16 * 1024;	/* Index block size in InnoDB: used by MySQL
+	stats.block_size = 16 * 1024;	/* Index block size in InnoDB: used by MySQL
 				in query optimization */
 
 	/* Init table lock structure */
@@ -2516,8 +2665,8 @@ get_innobase_type_from_mysql_type(
 	}
 
 	switch (field->type()) {
-	        /* NOTE that we only allow string types in DATA_MYSQL
-		and DATA_VARMYSQL */
+		/* NOTE that we only allow string types in DATA_MYSQL and
+		DATA_VARMYSQL */
                 case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
                 case MYSQL_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
 					if (field->binary()) {
@@ -2739,7 +2888,6 @@ ha_innobase::store_key_val_for_row(
 
 			CHARSET_INFO*	cs;
 			ulint		key_len;
-			ulint		len;
 			ulint		true_len;
 			int		error=0;
 			ulint		blob_len;
@@ -2886,7 +3034,7 @@ build_template(
 					only if templ_type is
 					ROW_MYSQL_REC_FIELDS */
 	TABLE*		table,		/* in: MySQL table */
-	ulint		templ_type)	/* in: ROW_MYSQL_WHOLE_ROW or
+	uint		templ_type)	/* in: ROW_MYSQL_WHOLE_ROW or
 					ROW_MYSQL_REC_FIELDS */
 {
 	dict_index_t*	index;
@@ -2913,16 +3061,16 @@ build_template(
 	     if (prebuilt->hint_need_to_fetch_extra_cols
 						== ROW_RETRIEVE_ALL_COLS) {
 
-		/* We know we must at least fetch all columns in the key, or
-		all columns in the table */
+			/* We know we must at least fetch all columns in the
+			key, or all columns in the table */
 
 		if (prebuilt->read_just_key) {
-			/* MySQL has instructed us that it is enough to
-			fetch the columns in the key; looks like MySQL
-			can set this flag also when there is only a
-			prefix of the column in the key: in that case we
-			retrieve the whole column from the clustered
-			index */
+				/* MySQL has instructed us that it is enough
+				to fetch the columns in the key; looks like
+				MySQL can set this flag also when there is
+				only a prefix of the column in the key: in
+				that case we retrieve the whole column from
+				the clustered index */
 
 			fetch_all_in_key = TRUE;
 		} else {
@@ -2930,11 +3078,12 @@ build_template(
 		}
 	    } else if (prebuilt->hint_need_to_fetch_extra_cols
 						== ROW_RETRIEVE_PRIMARY_KEY) {
-		/* We must at least fetch all primary key cols. Note that if
-		the clustered index was internally generated by InnoDB on the
-		row id (no primary key was defined), then
-		row_search_for_mysql() will always retrieve the row id to a
-		special buffer in the prebuilt struct. */
+			/* We must at least fetch all primary key cols. Note
+			   that if the clustered index was internally generated
+			   by InnoDB on the row id (no primary key was
+			   defined), then row_search_for_mysql() will always
+			   retrieve the row id to a special buffer in the
+			   prebuilt struct. */
 
 		fetch_primary_key_cols = TRUE;
 	    }
@@ -2994,15 +3143,16 @@ build_template(
 				goto include_field;
 			}
 
-			if (thd->query_id == field->query_id) {
+                        if (bitmap_is_set(table->read_set, i) ||
+                            bitmap_is_set(table->write_set, i)) {
 				/* This field is needed in the query */
 
 				goto include_field;
 			}
 
 			if (fetch_primary_key_cols
-			    && dict_table_col_in_clustered_key(index->table,
-									i)) {
+				&& dict_table_col_in_clustered_key(
+					index->table, i)) {
 				/* This field is needed in the query */
 
 				goto include_field;
@@ -3018,8 +3168,8 @@ include_field:
 		templ->col_no = i;
 
 		if (index == clust_index) {
-			templ->rec_field_no = (index->table->cols + i)
-								->clust_pos;
+			templ->rec_field_no = dict_col_get_clust_pos_noninline(
+				&index->table->cols[i], index);
 		} else {
 			templ->rec_field_no = dict_index_get_nth_col_pos(
 								index, i);
@@ -3048,7 +3198,7 @@ include_field:
 			mysql_prefix_len = templ->mysql_col_offset
 				+ templ->mysql_col_len;
 		}
-		templ->type = index->table->cols[i].type.mtype;
+		templ->type = index->table->cols[i].mtype;
 		templ->mysql_type = (ulint)field->type();
 
 		if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
@@ -3057,10 +3207,10 @@ include_field:
 		}
 
 		templ->charset = dtype_get_charset_coll_noninline(
-				index->table->cols[i].type.prtype);
-		templ->mbminlen = index->table->cols[i].type.mbminlen;
-		templ->mbmaxlen = index->table->cols[i].type.mbmaxlen;
-		templ->is_unsigned = index->table->cols[i].type.prtype
+				index->table->cols[i].prtype);
+		templ->mbminlen = index->table->cols[i].mbminlen;
+		templ->mbmaxlen = index->table->cols[i].mbmaxlen;
+		templ->is_unsigned = index->table->cols[i].prtype
 							& DATA_UNSIGNED;
 		if (templ->type == DATA_BLOB) {
 			prebuilt->templ_contains_blob = TRUE;
@@ -3078,8 +3228,9 @@ skip_field:
 		for (i = 0; i < n_requested_fields; i++) {
 			templ = prebuilt->mysql_template + i;
 
-			templ->rec_field_no =
-			    (index->table->cols + templ->col_no)->clust_pos;
+			templ->rec_field_no = dict_col_get_clust_pos_noninline(
+				&index->table->cols[templ->col_no],
+				clust_index);
 		}
 	}
 }
@@ -3103,11 +3254,11 @@ ha_innobase::write_row(
   	DBUG_ENTER("ha_innobase::write_row");
 
 	if (prebuilt->trx !=
-                        (trx_t*) current_thd->ha_data[innobase_hton.slot]) {
+			(trx_t*) current_thd->ha_data[innobase_hton->slot]) {
 	  sql_print_error("The transaction object for the table handle is at "
 			  "%p, but for the current thread it is at %p",
 			  prebuilt->trx,
-			  (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+			  (trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 		fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
 		ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
@@ -3115,7 +3266,7 @@ ha_innobase::write_row(
 			"InnoDB: Dump of 200 bytes around transaction.all: ",
 			stderr);
 		ut_print_buf(stderr,
-           	 ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100,
+		 ((byte*)(&(current_thd->ha_data[innobase_hton->slot]))) - 100,
 								200);
 		putc('\n', stderr);
 		ut_error;
@@ -3346,9 +3497,11 @@ calc_row_difference(
 	ulint		col_type;
 	ulint		n_changed = 0;
 	dfield_t	dfield;
+	dict_index_t*	clust_index;
 	uint		i;
 
 	n_fields = table->s->fields;
+	clust_index = dict_table_get_first_index_noninline(prebuilt->table);
 
 	/* We use upd_buff to convert changed fields */
 	buf = (byte*) upd_buff;
@@ -3379,7 +3532,7 @@ calc_row_difference(
 
 		field_mysql_type = field->type();
 
-		col_type = prebuilt->table->cols[i].type.mtype;
+		col_type = prebuilt->table->cols[i].mtype;
 
 		switch (col_type) {
 
@@ -3434,7 +3587,8 @@ calc_row_difference(
 			/* Let us use a dummy dfield to make the conversion
 			from the MySQL column format to the InnoDB format */
 
-			dfield.type = (prebuilt->table->cols + i)->type;
+			dict_col_copy_type_noninline(prebuilt->table->cols + i,
+						     &dfield.type);
 
 			if (n_len != UNIV_SQL_NULL) {
 				buf = row_mysql_store_col_in_innobase_format(
@@ -3443,7 +3597,8 @@ calc_row_difference(
 						TRUE,
 						new_mysql_row_col,
 						col_pack_len,
-						prebuilt->table->comp);
+					dict_table_is_comp_noninline(
+							prebuilt->table));
 				ufield->new_val.data = dfield.data;
 				ufield->new_val.len = dfield.len;
 			} else {
@@ -3452,7 +3607,8 @@ calc_row_difference(
 			}
 
 			ufield->exp = NULL;
-			ufield->field_no = prebuilt->table->cols[i].clust_pos;
+			ufield->field_no = dict_col_get_clust_pos_noninline(
+				&prebuilt->table->cols[i], clust_index);
 			n_changed++;
 		}
 	}
@@ -3486,8 +3642,8 @@ ha_innobase::update_row(
 
 	DBUG_ENTER("ha_innobase::update_row");
 
-	ut_ad(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
         if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
                 table->timestamp_field->set_time();
@@ -3547,8 +3703,8 @@ ha_innobase::delete_row(
 
 	DBUG_ENTER("ha_innobase::delete_row");
 
-	ut_ad(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 	if (last_query_id != user_thd->query_id) {
 	        prebuilt->sql_stat_start = TRUE;
@@ -3582,8 +3738,9 @@ ha_innobase::delete_row(
 }
 
 /**************************************************************************
-Removes a new lock set on a row. This method does nothing unless the
-option innodb_locks_unsafe_for_binlog is set.*/
+Removes a new lock set on a row, if it was not read optimistically. This can
+be called after a row has been read in the processing of an UPDATE or a DELETE
+query, if the option innodb_locks_unsafe_for_binlog is set. */
 
 void
 ha_innobase::unlock_row(void)
@@ -3593,7 +3750,7 @@ ha_innobase::unlock_row(void)
 
 	DBUG_ENTER("ha_innobase::unlock_row");
 
-	if (last_query_id != user_thd->query_id) {
+	if (UNIV_UNLIKELY(last_query_id != user_thd->query_id)) {
 		ut_print_timestamp(stderr);
 		sql_print_error("last_query_id is %lu != user_thd_query_id is "
 				"%lu", (ulong) last_query_id,
@@ -3609,12 +3766,55 @@ ha_innobase::unlock_row(void)
 		DBUG_VOID_RETURN;
 	}
 
-	if (srv_locks_unsafe_for_binlog) {
+	switch (prebuilt->row_read_type) {
+	case ROW_READ_WITH_LOCKS:
+		if (!srv_locks_unsafe_for_binlog
+		|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
+			break;
+		}
+		/* fall through */
+	case ROW_READ_TRY_SEMI_CONSISTENT:
 		row_unlock_for_mysql(prebuilt, FALSE);
+		break;
+	case ROW_READ_DID_SEMI_CONSISTENT:
+		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
+		break;
 	}
 
 	DBUG_VOID_RETURN;
+}
+
+/* See handler.h and row0mysql.h for docs on this function. */
+bool
+ha_innobase::was_semi_consistent_read(void)
+/*=======================================*/
+{
+	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 
+	return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
+}
+
+/* See handler.h and row0mysql.h for docs on this function. */
+void
+ha_innobase::try_semi_consistent_read(bool yes)
+/*===========================================*/
+{
+	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
+
+	/* Row read type is set to semi consistent read if this was
+	requested by the MySQL and either innodb_locks_unsafe_for_binlog
+	option is used or this session is using READ COMMITTED isolation
+	level. */
+
+	if (yes &&  (srv_locks_unsafe_for_binlog
+		|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
+		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
+	} else {
+		prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
+	}
 }
 
 /**********************************************************************
@@ -3624,7 +3824,8 @@ int
 ha_innobase::index_init(
 /*====================*/
 			/* out: 0 or error number */
-	uint 	keynr)	/* in: key (index) number */
+	uint	keynr,	/* in: key (index) number */
+	bool sorted)	/* in: 1 if result MUST be sorted according to index */
 {
 	int 	error	= 0;
   	DBUG_ENTER("index_init");
@@ -3767,8 +3968,8 @@ ha_innobase::index_read(
 
   	DBUG_ENTER("index_read");
 
-	ut_ad(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
   	statistic_increment(current_thd->status_var.ha_read_key_count,
 			    &LOCK_status);
@@ -3882,8 +4083,8 @@ ha_innobase::change_active_index(
 	DBUG_ENTER("change_active_index");
 
 	ut_ad(user_thd == current_thd);
-	ut_ad(prebuilt->trx ==
-             (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 	active_index = keynr;
 
@@ -3891,18 +4092,19 @@ ha_innobase::change_active_index(
 		key = table->key_info + active_index;
 
 		prebuilt->index = dict_table_get_index_noninline(
-						     prebuilt->table,
-						     key->name);
+			prebuilt->table, key->name);
         } else {
 		prebuilt->index = dict_table_get_first_index_noninline(
 							   prebuilt->table);
 	}
 
 	if (!prebuilt->index) {
-	       sql_print_error("Innodb could not find key n:o %u with name %s "
+		sql_print_error(
+			"Innodb could not find key n:o %u with name %s "
 			       "from dict cache for table %s",
 			       keynr, key ? key->name : "NULL",
 			       prebuilt->table->name);
+
 	      DBUG_RETURN(1);
 	}
 
@@ -3971,8 +4173,8 @@ ha_innobase::general_fetch(
 
 	DBUG_ENTER("general_fetch");
 
-	ut_ad(prebuilt->trx ==
-             (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 	innodb_srv_conc_enter_innodb(prebuilt->trx);
 
@@ -4130,6 +4332,13 @@ ha_innobase::rnd_init(
 		err = change_active_index(primary_key);
 	}
 
+	/* Don't use semi-consistent read in random row reads (by position).
+	This means we must disable semi_consistent_read if scan is false */
+
+	if (!scan) {
+		try_semi_consistent_read(0);
+	}
+
   	start_of_scan = 1;
 
  	return(err);
@@ -4200,8 +4409,8 @@ ha_innobase::rnd_pos(
 	statistic_increment(current_thd->status_var.ha_read_rnd_count,
 			    &LOCK_status);
 
-	ut_ad(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 	if (prebuilt->clust_index_was_generated) {
 		/* No primary key was defined for the table and we
@@ -4250,8 +4459,8 @@ ha_innobase::position(
 	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 	uint		len;
 
-	ut_ad(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 	if (prebuilt->clust_index_was_generated) {
 		/* No primary key was defined for the table and we
@@ -4294,7 +4503,7 @@ create_table_def(
 					an .ibd file for it (no .ibd extension
 					in the path, though); otherwise this
 					is NULL */
-	ibool		comp)		/* in: TRUE=compact record format */
+	ulint		flags)		/* in: table flags */
 {
 	Field*		field;
 	dict_table_t*	table;
@@ -4317,7 +4526,7 @@ create_table_def(
 	/* We pass 0 as the space id, and determine at a lower level the space
 	id where to store the table */
 
-	table = dict_mem_table_create(table_name, 0, n_cols, comp);
+	table = dict_mem_table_create(table_name, 0, n_cols, flags);
 
 	if (path_of_temp_table) {
 		table->dir_path_of_temp_table =
@@ -4379,8 +4588,7 @@ create_table_def(
 					     | nulls_allowed | unsigned_type
 					     | binary_type | long_true_varchar,
 					    charset_no),
-					col_len,
-					0);
+			col_len);
 	}
 
 	error = row_create_table_for_mysql(table, trx);
@@ -4482,7 +4690,8 @@ create_index(
 			    || col_type == DATA_FLOAT
 			    || col_type == DATA_DOUBLE
 			    || col_type == DATA_DECIMAL) {
-			  sql_print_error("MySQL is trying to create a column "
+				sql_print_error(
+					"MySQL is trying to create a column "
 					  "prefix index field, on an "
 					  "inappropriate data type. Table "
 					  "name %s, column name %s.",
@@ -4497,12 +4706,8 @@ create_index(
 
 		field_lengths[i] = key_part->length;
 
-		/* We assume all fields should be sorted in ascending
-		order, hence the '0': */
-
 		dict_mem_index_add_field(index,
-				(char*) key_part->field->field_name,
-				0, prefix_len);
+			(char*) key_part->field->field_name, prefix_len);
 	}
 
 	/* Even though we've defined max_supported_key_part_length, we
@@ -4534,8 +4739,7 @@ create_clustered_index_when_no_primary(
 	id where to store the table */
 
 	index = dict_mem_index_create((char*) table_name,
-				      (char*) "GEN_CLUST_INDEX",
-				      0, DICT_CLUSTERED, 0);
+		(char*) "GEN_CLUST_INDEX", 0, DICT_CLUSTERED, 0);
 	error = row_create_index_for_mysql(index, trx, NULL);
 
 	error = convert_error_code_to_mysql(error, NULL);
@@ -4567,6 +4771,7 @@ ha_innobase::create(
 	char		norm_name[FN_REFLEN];
 	THD		*thd= current_thd;
 	ib_longlong     auto_inc_value;
+	ulint		flags;
 
   	DBUG_ENTER("ha_innobase::create");
 
@@ -4582,7 +4787,7 @@ ha_innobase::create(
 	/* Get the transaction associated with the current thd, or create one
 	if not yet created */
 
-	parent_trx = check_trx_exists(current_thd);
+	parent_trx = check_trx_exists(thd);
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
@@ -4608,7 +4813,7 @@ ha_innobase::create(
 		srv_lower_case_table_names = FALSE;
 	}
 
-	fn_format(name2, name, "", "", 2);	// Remove the .frm extension
+	strcpy(name2, name);
 
 	normalize_table_name(norm_name, name2);
 
@@ -4620,9 +4825,15 @@ ha_innobase::create(
 
 	/* Create the table definition in InnoDB */
 
+	flags = 0;
+
+	if (form->s->row_type != ROW_TYPE_REDUNDANT) {
+		flags |= DICT_TF_COMPACT;
+	}
+
 	error = create_table_def(trx, form, norm_name,
 		create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
-		form->s->row_type != ROW_TYPE_REDUNDANT);
+		flags);
 
   	if (error) {
 		goto cleanup;
@@ -4630,8 +4841,8 @@ ha_innobase::create(
 
 	/* Look for a primary key */
 
-	primary_key_no= (table->s->primary_key != MAX_KEY ?
-			 (int) table->s->primary_key :
+	primary_key_no= (form->s->primary_key != MAX_KEY ?
+			 (int) form->s->primary_key :
 			 -1);
 
 	/* Our function row_get_mysql_key_number_for_index assumes
@@ -4672,20 +4883,9 @@ ha_innobase::create(
       		}
   	}
 
-	if (current_thd->query != NULL) {
-		LEX_STRING q;
-
-		if (thd->convert_string(&q, system_charset_info,
-					current_thd->query,
-					current_thd->query_length,
-					current_thd->charset())) {
-			error = HA_ERR_OUT_OF_MEM;
-
-			goto cleanup;
-		}
-
+	if (thd->query != NULL) {
 		error = row_table_add_foreign_constraints(trx,
-			q.str, norm_name,
+			thd->query, norm_name,
 			create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
 		error = convert_error_code_to_mysql(error, NULL);
@@ -4705,7 +4905,7 @@ ha_innobase::create(
 
 	log_buffer_flush_to_disk();
 
-	innobase_table = dict_table_get(norm_name, NULL);
+	innobase_table = dict_table_get(norm_name);
 
 	DBUG_ASSERT(innobase_table != 0);
 
@@ -4760,7 +4960,7 @@ ha_innobase::discard_or_import_tablespac
 
 	ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
 	ut_a(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 	dict_table = prebuilt->table;
 	trx = prebuilt->trx;
@@ -4786,7 +4986,6 @@ ha_innobase::delete_all_rows(void)
 {
 	row_prebuilt_t*	prebuilt	= (row_prebuilt_t*)innobase_prebuilt;
 	int		error;
-	trx_t*		trx;
 	THD*		thd		= current_thd;
 
 	DBUG_ENTER("ha_innobase::delete_all_rows");
@@ -4799,13 +4998,13 @@ ha_innobase::delete_all_rows(void)
 	}
 
 	/* Get the transaction associated with the current thd, or create one
-	if not yet created */
+	if not yet created, and update prebuilt->trx */
 
-	trx = check_trx_exists(thd);
+	update_thd(thd);
 
 	/* Truncate the table in InnoDB */
 
-	error = row_truncate_table_for_mysql(prebuilt->table, trx);
+	error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
 	if (error == DB_ERROR) {
 		/* Cannot truncate; resort to ha_innobase::delete_row() */
 		goto fallback;
@@ -4841,7 +5040,7 @@ ha_innobase::delete_table(
 	/* Get the transaction associated with the current thd, or create one
 	if not yet created */
 
-	parent_trx = check_trx_exists(current_thd);
+	parent_trx = check_trx_exists(thd);
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
@@ -4904,7 +5103,7 @@ ha_innobase::delete_table(
 /*********************************************************************
 Removes all tables in the named database inside InnoDB. */
 
-int
+void
 innobase_drop_database(
 /*===================*/
 			/* out: error number */
@@ -4970,10 +5169,13 @@ innobase_drop_database(
 
   	innobase_commit_low(trx);
   	trx_free_for_mysql(trx);
-
+#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR
 	error = convert_error_code_to_mysql(error, NULL);
 
 	return(error);
+#else
+	return;
+#endif
 }
 
 /*************************************************************************
@@ -5085,6 +5287,9 @@ ha_innobase::records_in_range(
 
    	DBUG_ENTER("records_in_range");
 
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
+
 	prebuilt->trx->op_info = (char*)"estimating records in index range";
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
@@ -5312,13 +5517,11 @@ ha_innobase::info(
 
 		if (ib_table->space != 0) {
 			my_snprintf(path, sizeof(path), "%s/%s%s",
-				    mysql_data_home, ib_table->name,
-				    ".ibd");
+				mysql_data_home, ib_table->name, ".ibd");
 			unpack_filename(path,path);
 		} else {
 			my_snprintf(path, sizeof(path), "%s/%s%s",
-				    mysql_data_home, ib_table->name,
-				    reg_ext);
+				mysql_data_home, ib_table->name, reg_ext);
 
 			unpack_filename(path,path);
 		}
@@ -5327,7 +5530,7 @@ ha_innobase::info(
 		nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
 
 		if (os_file_get_status(path,&stat_info)) {
-			create_time = stat_info.ctime;
+			stats.create_time = stat_info.ctime;
 		}
  	}
 
@@ -5355,21 +5558,21 @@ ha_innobase::info(
 			n_rows++;
 		}
 
-    		records = (ha_rows)n_rows;
-    		deleted = 0;
-    		data_file_length = ((ulonglong)
+		stats.records = (ha_rows)n_rows;
+		stats.deleted = 0;
+		stats.data_file_length = ((ulonglong)
 				ib_table->stat_clustered_index_size)
     					* UNIV_PAGE_SIZE;
-    		index_file_length = ((ulonglong)
+		stats.index_file_length = ((ulonglong)
 				ib_table->stat_sum_of_other_index_sizes)
     					* UNIV_PAGE_SIZE;
-    		delete_length = 0;
-    		check_time = 0;
+		stats.delete_length = 0;
+		stats.check_time = 0;
 
-    		if (records == 0) {
-    			mean_rec_length = 0;
+		if (stats.records == 0) {
+			stats.mean_rec_length = 0;
     		} else {
-    			mean_rec_length = (ulong) (data_file_length / records);
+			stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
     		}
     	}
 
@@ -5389,7 +5592,7 @@ ha_innobase::info(
 						".frm file. Have you mixed up "
 						".frm files from different "
 						"installations? See "
-"http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n",
+"http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
 
 						ib_table->name);
 				break;
@@ -5403,7 +5606,7 @@ ha_innobase::info(
 "Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
 "statistics for %lu columns. Have you mixed up .frm files from different "
 "installations? "
-"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n",
+"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
 							index->name,
 							ib_table->name,
 							(unsigned long)
@@ -5413,9 +5616,9 @@ ha_innobase::info(
 
 				if (index->stat_n_diff_key_vals[j + 1] == 0) {
 
-					rec_per_key = records;
+					rec_per_key = stats.records;
 				} else {
-					rec_per_key = (ha_rows)(records /
+					rec_per_key = (ha_rows)(stats.records /
    				         index->stat_n_diff_key_vals[j + 1]);
 				}
 
@@ -5443,8 +5646,7 @@ ha_innobase::info(
 		ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
 
 		errkey = (unsigned int) row_get_mysql_key_number_for_index(
-				       (dict_index_t*)
-				       trx_get_error_info(prebuilt->trx));
+			(dict_index_t*) trx_get_error_info(prebuilt->trx));
   	}
 
 	if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
@@ -5471,7 +5673,7 @@ ha_innobase::info(
 			}
 		}
 
-		auto_increment_value = auto_inc;
+		stats.auto_increment_value = auto_inc;
 	}
 
 	prebuilt->trx->op_info = (char*)"";
@@ -5497,7 +5699,7 @@ ha_innobase::analyze(
 }
 
 /**************************************************************************
-This is mapped to "ALTER TABLE tablename TYPE=InnoDB", which rebuilds
+This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
 the table in MySQL. */
 
 int
@@ -5528,7 +5730,7 @@ ha_innobase::check(
 
 	ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
 	ut_a(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
 
 	if (prebuilt->mysql_template == NULL) {
 		/* Build the template; we will use a dummy template
@@ -5699,8 +5901,7 @@ ha_innobase::get_foreign_key_list(THD *t
   mutex_enter_noninline(&(dict_sys->mutex));
   foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
-  while (foreign != NULL)
-  {
+  while (foreign != NULL) {
     uint i;
     FOREIGN_KEY_INFO f_key_info;
     LEX_STRING *name= 0;
@@ -5723,53 +5924,69 @@ ha_innobase::get_foreign_key_list(THD *t
     f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff,
                                                (uint) strlen(tmp_buff), 1);
 
-    for (i= 0;;)
-    {
+	  for (i= 0;;) {
       tmp_buff= foreign->foreign_col_names[i];
-      name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
+		  name= make_lex_string(thd, name, tmp_buff,
+			  (uint) strlen(tmp_buff), 1);
       f_key_info.foreign_fields.push_back(name);
       tmp_buff= foreign->referenced_col_names[i];
-      name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
+		  name= make_lex_string(thd, name, tmp_buff,
+			  (uint) strlen(tmp_buff), 1);
       f_key_info.referenced_fields.push_back(name);
       if (++i >= foreign->n_fields)
         break;
     }
 
-    ulong length= 0;
-    if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE)
+          ulong length;
+          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
+          {
+            length=7;
+            tmp_buff= "CASCADE";
+          }	
+          else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
+          {
+            length=8;
+            tmp_buff= "SET NULL";
+          }
+          else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
     {
-      length=17;
-      tmp_buff= "ON DELETE CASCADE";
+            length=9;
+            tmp_buff= "NO ACTION";
     }
-    else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL)
+          else
     {
-      length=18;
-      tmp_buff= "ON DELETE SET NULL";
+            length=8;
+            tmp_buff= "RESTRICT";
     }
-    else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION)
+          f_key_info.delete_method= make_lex_string(thd, f_key_info.delete_method,
+                                                    tmp_buff, length, 1);
+ 
+ 
+          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
     {
-      length=19;
-      tmp_buff= "ON DELETE NO ACTION";
+            length=7;
+            tmp_buff= "CASCADE";
     }
-    else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE)
+          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
     {
-      length=17;
-      tmp_buff= "ON UPDATE CASCADE";
+            length=8;
+            tmp_buff= "SET NULL";
     }
-    else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL)
+          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
     {
-      length=18;
-      tmp_buff= "ON UPDATE SET NULL";
+            length=9;
+            tmp_buff= "NO ACTION";
     }
-    else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION)
+          else
     {
-      length=19;
-      tmp_buff= "ON UPDATE NO ACTION";
+            length=8;
+            tmp_buff= "RESTRICT";
     }
-    f_key_info.constraint_method= make_lex_string(thd,
-                                                  f_key_info.constraint_method,
+          f_key_info.update_method= make_lex_string(thd, f_key_info.update_method,
                                                   tmp_buff, length, 1);
 
+
+
     FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
                                     thd->memdup((gptr) &f_key_info,
                                                 sizeof(FOREIGN_KEY_INFO)));
@@ -5778,6 +5995,7 @@ ha_innobase::get_foreign_key_list(THD *t
   }
   mutex_exit_noninline(&(dict_sys->mutex));
   prebuilt->trx->op_info = (char*)"";
+
   DBUG_RETURN(0);
 }
 
@@ -5794,6 +6012,10 @@ ha_innobase::can_switch_engines(void)
 	bool	can_switch;
 
  	DBUG_ENTER("ha_innobase::can_switch_engines");
+
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[innobase_hton->slot]);
+
 	prebuilt->trx->op_info =
 			"determining if there are foreign key constraints";
 	row_mysql_lock_data_dictionary(prebuilt->trx);
@@ -5850,8 +6072,7 @@ ha_innobase::extra(
 /*===============*/
 			   /* out: 0 or error number */
 	enum ha_extra_function operation)
-                           /* in: HA_EXTRA_RETRIEVE_ALL_COLS or some
-			   other flag */
+			   /* in: HA_EXTRA_FLUSH or some other flag */
 {
 	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 
@@ -5865,13 +6086,6 @@ ha_innobase::extra(
                                 row_mysql_prebuilt_free_blob_heap(prebuilt);
                         }
                         break;
-                case HA_EXTRA_RESET:
-                        if (prebuilt->blob_heap) {
-                                row_mysql_prebuilt_free_blob_heap(prebuilt);
-                        }
-                        prebuilt->keep_other_fields_on_keyread = 0;
-                        prebuilt->read_just_key = 0;
-                        break;
   		case HA_EXTRA_RESET_STATE:
 	        	prebuilt->keep_other_fields_on_keyread = 0;
 	        	prebuilt->read_just_key = 0;
@@ -5879,16 +6093,6 @@ ha_innobase::extra(
 		case HA_EXTRA_NO_KEYREAD:
     			prebuilt->read_just_key = 0;
     			break;
-	        case HA_EXTRA_RETRIEVE_ALL_COLS:
-			prebuilt->hint_need_to_fetch_extra_cols
-					= ROW_RETRIEVE_ALL_COLS;
-			break;
-	        case HA_EXTRA_RETRIEVE_PRIMARY_KEY:
-			if (prebuilt->hint_need_to_fetch_extra_cols == 0) {
-				prebuilt->hint_need_to_fetch_extra_cols
-					= ROW_RETRIEVE_PRIMARY_KEY;
-			}
-			break;
 	        case HA_EXTRA_KEYREAD:
 	        	prebuilt->read_just_key = 1;
 	        	break;
@@ -5902,6 +6106,18 @@ ha_innobase::extra(
 	return(0);
 }
 
+int ha_innobase::reset()
+{
+  row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+  if (prebuilt->blob_heap) {
+    row_mysql_prebuilt_free_blob_heap(prebuilt);
+  }
+  prebuilt->keep_other_fields_on_keyread = 0;
+  prebuilt->read_just_key = 0;
+  return 0;
+}
+
+
 /**********************************************************************
 MySQL calls this function at the start of each SQL statement inside LOCK
 TABLES. Inside LOCK TABLES the ::external_lock method does not work to
@@ -5965,7 +6181,7 @@ ha_innobase::start_stmt(
 			1) ::store_lock(),
 			2) ::external_lock(),
 			3) ::init_table_handle_for_HANDLER(), and
-			4) :.transactional_table_lock(). */
+			4) ::transactional_table_lock(). */
 
 			prebuilt->select_lock_type =
 				prebuilt->stored_select_lock_type;
@@ -6062,12 +6278,6 @@ ha_innobase::external_lock(
 		trx->n_mysql_tables_in_use++;
 		prebuilt->mysql_has_locked = TRUE;
 
-		if (trx->n_mysql_tables_in_use == 1) {
-		        trx->isolation_level = innobase_map_isolation_level(
-						(enum_tx_isolation)
-						thd->variables.tx_isolation);
-		}
-
 		if (trx->isolation_level == TRX_ISO_SERIALIZABLE
 		    && prebuilt->select_lock_type == LOCK_NONE
 		    && (thd->options
@@ -6103,9 +6313,8 @@ ha_innobase::external_lock(
 			    thd->variables.innodb_table_locks &&
 			    (thd->options & OPTION_NOT_AUTOCOMMIT)) {
 
-				ulint	error;
-				error = row_lock_table_for_mysql(prebuilt,
-							NULL, 0);
+				ulint	error = row_lock_table_for_mysql(
+					prebuilt, NULL, 0);
 
 				if (error != DB_SUCCESS) {
 					error = convert_error_code_to_mysql(
@@ -6188,7 +6397,7 @@ ha_innobase::transactional_table_lock(
 "table %s does not exist.\n"
 "Have you deleted the .ibd file from the database directory under\n"
 "the MySQL datadir?"
-"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
+"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
 "how you can resolve the problem.\n",
 				prebuilt->table->name);
 		DBUG_RETURN(HA_ERR_CRASHED);
@@ -6252,13 +6461,17 @@ ha_innobase::transactional_table_lock(
 /****************************************************************************
 Here we export InnoDB status variables to MySQL.  */
 
-void
-innodb_export_status(void)
-/*======================*/
+int
+innodb_export_status()
+/*==================*/
 {
+	if (innodb_inited) {
   srv_export_innodb_status();
 }
 
+	return 0;
+}
+
 /****************************************************************************
 Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
 Monitor to the client. */
@@ -6266,9 +6479,9 @@ Monitor to the client. */
 bool
 innodb_show_status(
 /*===============*/
-	THD*	thd)	/* in: the MySQL query thread of the caller */
+	THD*	thd,	/* in: the MySQL query thread of the caller */
+	stat_print_fn *stat_print)
 {
-	Protocol*		protocol = thd->protocol;
 	trx_t*			trx;
 	static const char	truncated_msg[] = "... truncated...\n";
 	const long		MAX_STATUS_SIZE = 64000;
@@ -6278,10 +6491,7 @@ innodb_show_status(
         DBUG_ENTER("innodb_show_status");
 
         if (have_innodb != SHOW_OPTION_YES) {
-                my_message(ER_NOT_SUPPORTED_YET,
-          "Cannot call SHOW INNODB STATUS because skip-innodb is defined",
-                           MYF(0));
-                DBUG_RETURN(TRUE);
+		DBUG_RETURN(FALSE);
         }
 
 	trx = check_trx_exists(thd);
@@ -6314,8 +6524,7 @@ innodb_show_status(
 	/* allocate buffer for the string, and
 	read the contents of the temporary file */
 
-	if (!(str = my_malloc(usable_len + 1, MYF(0))))
-        {
+	if (!(str = my_malloc(usable_len + 1, MYF(0)))) {
           mutex_exit_noninline(&srv_monitor_file_mutex);
           DBUG_RETURN(TRUE);
         }
@@ -6343,27 +6552,14 @@ innodb_show_status(
 
 	mutex_exit_noninline(&srv_monitor_file_mutex);
 
-	List<Item> field_list;
-
-	field_list.push_back(new Item_empty_string("Status", flen));
-
-	if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
-                                               Protocol::SEND_EOF)) {
-		my_free(str, MYF(0));
+	bool result = FALSE;
 
-		DBUG_RETURN(TRUE);
+	if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name),
+			STRING_WITH_LEN(""), str, flen)) {
+		result= TRUE;
 	}
-
-        protocol->prepare_for_resend();
-        protocol->store(str, flen, system_charset_info);
         my_free(str, MYF(0));
 
-        if (protocol->write()) {
-
-        	DBUG_RETURN(TRUE);
-	}
-	send_eof(thd);
-
   	DBUG_RETURN(FALSE);
 }
 
@@ -6372,11 +6568,12 @@ Implements the SHOW MUTEX STATUS command
 
 bool
 innodb_mutex_show_status(
-/*===============*/
-  THD*  thd)  /* in: the MySQL query thread of the caller */
+/*=====================*/
+	THD*		thd,		/* in: the MySQL query thread of the
+					caller */
+	stat_print_fn*	stat_print)
 {
-  Protocol        *protocol= thd->protocol;
-  List<Item> field_list;
+	char buf1[IO_SIZE], buf2[IO_SIZE];
   mutex_t*  mutex;
   ulint   rw_lock_count= 0;
   ulint   rw_lock_count_spin_loop= 0;
@@ -6384,45 +6581,36 @@ innodb_mutex_show_status(
   ulint   rw_lock_count_os_wait= 0;
   ulint   rw_lock_count_os_yield= 0;
   ulonglong rw_lock_wait_time= 0;
+	uint	  hton_name_len= strlen(innobase_hton_name), buf1len, buf2len;
   DBUG_ENTER("innodb_mutex_show_status");
 
-  field_list.push_back(new Item_empty_string("Mutex", FN_REFLEN));
-  field_list.push_back(new Item_empty_string("Module", FN_REFLEN));
-  field_list.push_back(new Item_uint("Count", 21));
-  field_list.push_back(new Item_uint("Spin_waits", 21));
-  field_list.push_back(new Item_uint("Spin_rounds", 21));
-  field_list.push_back(new Item_uint("OS_waits", 21));
-  field_list.push_back(new Item_uint("OS_yields", 21));
-  field_list.push_back(new Item_uint("OS_waits_time", 21));
-
-  if (protocol->send_fields(&field_list,
-                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
-    DBUG_RETURN(TRUE);
-
 #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
     mutex_enter(&mutex_list_mutex);
 #endif
 
   mutex = UT_LIST_GET_FIRST(mutex_list);
 
-  while ( mutex != NULL )
-  {
-    if (mutex->mutex_type != 1)
-    {
-      if (mutex->count_using > 0)
-      {
-        protocol->prepare_for_resend();
-        protocol->store(mutex->cmutex_name, system_charset_info);
-        protocol->store(mutex->cfile_name, system_charset_info);
-        protocol->store((ulonglong)mutex->count_using);
-        protocol->store((ulonglong)mutex->count_spin_loop);
-        protocol->store((ulonglong)mutex->count_spin_rounds);
-        protocol->store((ulonglong)mutex->count_os_wait);
-        protocol->store((ulonglong)mutex->count_os_yield);
-        protocol->store((ulonglong)mutex->lspent_time/1000);
-
-        if (protocol->write())
-        {
+	while (mutex != NULL) {
+		if (mutex->mutex_type != 1) {
+			if (mutex->count_using > 0) {
+				buf1len= my_snprintf(buf1, sizeof(buf1),
+					"%s:%s",
+					mutex->cmutex_name, mutex->cfile_name);
+				buf2len= my_snprintf(buf2, sizeof(buf2),
+					"count=%lu, spin_waits=%lu,"
+					" spin_rounds=%lu, "
+					"os_waits=%lu, os_yields=%lu,"
+					" os_wait_times=%lu",
+					mutex->count_using,
+					mutex->count_spin_loop,
+					mutex->count_spin_rounds,
+					mutex->count_os_wait,
+					mutex->count_os_yield,
+					mutex->lspent_time/1000);
+
+				if (stat_print(thd, innobase_hton_name,
+						hton_name_len, buf1, buf1len,
+						buf2, buf2len)) {
 #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
           mutex_exit(&mutex_list_mutex);
 #endif
@@ -6430,8 +6618,7 @@ innodb_mutex_show_status(
         }
       }
     }
-    else
-    {
+		else {
       rw_lock_count += mutex->count_using;
       rw_lock_count_spin_loop += mutex->count_spin_loop;
       rw_lock_count_spin_rounds += mutex->count_spin_rounds;
@@ -6443,28 +6630,40 @@ innodb_mutex_show_status(
     mutex = UT_LIST_GET_NEXT(list, mutex);
   }
 
-  protocol->prepare_for_resend();
-  protocol->store("rw_lock_mutexes", system_charset_info);
-  protocol->store("", system_charset_info);
-  protocol->store((ulonglong)rw_lock_count);
-  protocol->store((ulonglong)rw_lock_count_spin_loop);
-  protocol->store((ulonglong)rw_lock_count_spin_rounds);
-  protocol->store((ulonglong)rw_lock_count_os_wait);
-  protocol->store((ulonglong)rw_lock_count_os_yield);
-  protocol->store((ulonglong)rw_lock_wait_time/1000);
+	buf2len= my_snprintf(buf2, sizeof(buf2),
+		"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+		"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+		rw_lock_count, rw_lock_count_spin_loop,
+		rw_lock_count_spin_rounds,
+		rw_lock_count_os_wait, rw_lock_count_os_yield,
+		rw_lock_wait_time/1000);
 
-  if (protocol->write())
-  {
+	if (stat_print(thd, innobase_hton_name, hton_name_len,
+			STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
     DBUG_RETURN(1);
   }
 
 #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
       mutex_exit(&mutex_list_mutex);
 #endif
-  send_eof(thd);
+
   DBUG_RETURN(FALSE);
 }
 
+bool innobase_show_status(THD* thd, stat_print_fn* stat_print,
+	enum ha_stat_type stat_type)
+{
+	switch (stat_type) {
+	case HA_ENGINE_STATUS:
+		return innodb_show_status(thd, stat_print);
+	case HA_ENGINE_MUTEX:
+		return innodb_mutex_show_status(thd, stat_print);
+	default:
+		return FALSE;
+	}
+}
+
+
 /****************************************************************************
  Handling the shared INNOBASE_SHARE structure that is needed to provide table
  locking.
@@ -6474,6 +6673,7 @@ static mysql_byte* innobase_get_key(INNO
 			      my_bool not_used __attribute__((unused)))
 {
   *length=share->table_name_length;
+
   return (mysql_byte*) share->table_name;
 }
 
@@ -6515,13 +6715,14 @@ static INNOBASE_SHARE *get_share(const c
 static void free_share(INNOBASE_SHARE *share)
 {
   pthread_mutex_lock(&innobase_share_mutex);
-  if (!--share->use_count)
-  {
+
+	if (!--share->use_count) {
     hash_delete(&innobase_open_tables, (mysql_byte*) share);
     thr_lock_delete(&share->lock);
     pthread_mutex_destroy(&share->mutex);
     my_free((gptr) share, MYF(0));
   }
+
   pthread_mutex_unlock(&innobase_share_mutex);
 }
 
@@ -6550,12 +6751,35 @@ ha_innobase::store_lock(
 						TL_IGNORE */
 {
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
+	trx_t*		trx;
+
+	/* Note that trx in this function is NOT necessarily prebuilt->trx
+	because we call update_thd() later, in ::external_lock()! Failure to
+	understand this caused a serious memory corruption bug in 5.1.11. */
+
+	trx = check_trx_exists(thd);
 
 	/* NOTE: MySQL  can call this function with lock 'type' TL_IGNORE!
 	Be careful to ignore TL_IGNORE if we are going to do something with
 	only 'real' locks! */
 
-	if ((lock_type == TL_READ && thd->in_lock_tables) ||
+	/* If no MySQL table is in use, we need to set the isolation level
+	of the transaction. */
+
+	if (lock_type != TL_IGNORE
+	&& trx->n_mysql_tables_in_use == 0) {
+		trx->isolation_level = innobase_map_isolation_level(
+						(enum_tx_isolation)
+						thd->variables.tx_isolation);
+	}
+
+	if (thd->lex->sql_command == SQLCOM_DROP_TABLE) {
+
+		/* MySQL calls this function in DROP TABLE though this table
+		handle may belong to another thd that is running a query. Let
+		us in that case skip any changes to the prebuilt struct. */ 
+
+	} else if ((lock_type == TL_READ && thd->in_lock_tables) ||
 	    (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
 	    lock_type == TL_READ_WITH_SHARED_LOCKS ||
 	    lock_type == TL_READ_NO_INSERT ||
@@ -6579,15 +6803,21 @@ ha_innobase::store_lock(
 		unexpected if an obsolete consistent read view would be
 		used. */
 
-		if (srv_locks_unsafe_for_binlog &&
-		    prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE &&
-		    (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
-		    (thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
-		     thd->lex->sql_command == SQLCOM_UPDATE ||
-		     thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
+		ulint	isolation_level;
 
-			/* In case we have innobase_locks_unsafe_for_binlog
-			option set and isolation level of the transaction
+		isolation_level = trx->isolation_level;
+
+		if ((srv_locks_unsafe_for_binlog
+			|| isolation_level == TRX_ISO_READ_COMMITTED)
+		&& isolation_level != TRX_ISO_SERIALIZABLE
+		&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
+		&& (thd->lex->sql_command == SQLCOM_INSERT_SELECT
+			|| thd->lex->sql_command == SQLCOM_UPDATE
+			|| thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
+
+			/* If we either have innobase_locks_unsafe_for_binlog
+			option set or this session is using READ COMMITTED
+			isolation level and isolation level of the transaction
 			is not set to serializable and MySQL is doing
 			INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 			CREATE  ... SELECT... without FOR UPDATE or
@@ -6718,10 +6948,11 @@ ha_innobase::innobase_read_and_init_auto
   	int     	error;
 
   	ut_a(prebuilt);
-	ut_a(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 	ut_a(prebuilt->table);
 
+	/* Prepare prebuilt->trx in the table handle */
+	update_thd(current_thd);
+
 	if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
 		trx_was_not_started = TRUE;
 	}
@@ -6762,7 +6993,7 @@ ha_innobase::innobase_read_and_init_auto
 	}
 
   	(void) extra(HA_EXTRA_KEYREAD);
-  	index_init(table->s->next_number_index);
+	index_init(table->s->next_number_index, 1);
 
 	/* Starting from 5.0.9, we use a consistent read to read the auto-inc
 	column maximum value. This eliminates the spurious deadlocks caused
@@ -6806,10 +7037,16 @@ ha_innobase::innobase_read_and_init_auto
 		'found_next_number_field' below because MySQL in SHOW TABLE
 		STATUS does not seem to set 'next_number_field'. The comment
 		in table.h says that 'next_number_field' is set when it is
-		'active'. */
+		'active'.
+		Since 5.1 MySQL enforces that we announce fields which we will
+		read; as we only do a val_*() call, dbug_tmp_use_all_columns()
+		with read_set is sufficient. */
 
+		my_bitmap_map *old_map;
+		old_map= dbug_tmp_use_all_columns(table, table->read_set);
     		auto_inc = (longlong) table->found_next_number_field->
                         	val_int_offset(table->s->rec_buff_length) + 1;
+		dbug_tmp_restore_column_map(table->read_set, old_map);
   	}
 
 	dict_table_autoinc_initialize(prebuilt->table, auto_inc);
@@ -6837,21 +7074,28 @@ func_exit_early:
  	return(error);
 }
 
-/***********************************************************************
+/*******************************************************************************
 This function initializes the auto-inc counter if it has not been
 initialized yet. This function does not change the value of the auto-inc
 counter if it already has been initialized. Returns the value of the
-auto-inc counter. */
+auto-inc counter in *first_value, and ULONGLONG_MAX in *nb_reserved_values (as
+we have a table-level lock). offset, increment, nb_desired_values are ignored.
+*first_value is set to -1 if error (deadlock or lock wait timeout)            */
 
-ulonglong
-ha_innobase::get_auto_increment()
-/*=============================*/
-                         /* out: auto-increment column value, -1 if error
-                         (deadlock or lock wait timeout) */
+void ha_innobase::get_auto_increment(
+/*=================================*/
+        ulonglong offset,              /* in */
+        ulonglong increment,           /* in */
+        ulonglong nb_desired_values,   /* in */
+        ulonglong *first_value,        /* out */
+        ulonglong *nb_reserved_values) /* out */
 {
   	longlong        nr;
   	int     	error;
 
+	/* Prepare prebuilt->trx in the table handle */
+	update_thd(current_thd);
+
 	error = innobase_read_and_init_auto_inc(&nr);
 
 	if (error) {
@@ -6862,10 +7106,13 @@ ha_innobase::get_auto_increment()
 		ut_print_timestamp(stderr);
 		sql_print_error("Error %lu in ::get_auto_increment()",
 				(ulong) error);
-          	return(~(ulonglong) 0);
+                *first_value= (~(ulonglong) 0);
+		return;
 	}
 
-	return((ulonglong) nr);
+        *first_value= (ulonglong) nr;
+        /* table-level autoinc lock reserves up to +inf */
+        *nb_reserved_values= ULONGLONG_MAX;
 }
 
 /* See comment in handler.h */
@@ -6877,6 +7124,8 @@ ha_innobase::reset_auto_increment(ulongl
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
   	int     	error;
 
+	update_thd(current_thd);
+
 	error = row_lock_table_autoinc_for_mysql(prebuilt);
 
 	if (error != DB_SUCCESS) {
@@ -7121,7 +7370,9 @@ innobase_xa_prepare(
 	int error = 0;
         trx_t* trx = check_trx_exists(thd);
 
-        if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
+	if (thd->lex->sql_command != SQLCOM_XA_PREPARE &&
+	    (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))))
+	{
 
                 /* For ibbackup to work the order of transactions in binlog
                 and InnoDB must be the same. Consider the situation
@@ -7306,4 +7557,63 @@ innobase_set_cursor_view(
 						(cursor_view_t*) curview);
 }
 
-#endif /* HAVE_INNOBASE_DB */
+
+bool ha_innobase::check_if_incompatible_data(
+	HA_CREATE_INFO*	info,
+	uint		table_changes)
+{
+	if (table_changes != IS_EQUAL_YES) {
+
+		return COMPATIBLE_DATA_NO;
+	}
+
+	/* Check that auto_increment value was not changed */
+	if ((info->used_fields & HA_CREATE_USED_AUTO) &&
+		info->auto_increment_value != 0) {
+
+		return COMPATIBLE_DATA_NO;
+	}
+
+	/* Check that row format didn't change */
+	if ((info->used_fields & HA_CREATE_USED_AUTO) &&
+		get_row_type() != info->row_type) {
+
+		return COMPATIBLE_DATA_NO;
+	}
+
+	return COMPATIBLE_DATA_YES;
+}
+
+static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
+{
+  innodb_export_status();
+  var->type= SHOW_ARRAY;
+  var->value= (char *) &innodb_status_variables;
+  return 0;
+}
+
+SHOW_VAR innodb_status_variables_export[]= {
+  {"Innodb",                   (char*) &show_innodb_vars, SHOW_FUNC},
+  {NullS, NullS, SHOW_LONG}
+};
+
+struct st_mysql_storage_engine innobase_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION, innobase_hton};
+
+mysql_declare_plugin(innobase)
+{
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &innobase_storage_engine,
+  innobase_hton_name,
+  "Innobase OY",
+  "Supports transactions, row-level locking, and foreign keys",
+  innobase_init, /* Plugin Init */
+  NULL, /* Plugin Deinit */
+  0x0100 /* 1.0 */,
+  innodb_status_variables_export,/* status variables             */
+  NULL,                       /* system variables                */
+  NULL                        /* config options                  */
+}
+mysql_declare_plugin_end;
+
+#endif
Thread
bk commit into 5.1 tree (cmiller:1.2334)Chad MILLER28 Sep