List:Commits« Previous MessageNext Message »
From:monty Date:February 22 2007 3:57pm
Subject:bk commit into 5.1 tree (monty:1.2453)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of monty. When monty 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, 2007-02-22 17:57:00+02:00, monty@stripped +39 -0
  Merge mysql.com:/home/my/mysql-5.0
  into  mysql.com:/home/my/mysql-5.1
  MERGE: 1.1810.2372.97

  BitKeeper/deleted/.del-ha_berkeley.cc@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.151.8.2

  BitKeeper/deleted/.del-ha_berkeley.cc@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: sql/ha_berkeley.cc -> BitKeeper/deleted/.del-ha_berkeley.cc

  BitKeeper/deleted/.del-ha_berkeley.h@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.70.6.2

  BitKeeper/deleted/.del-ha_berkeley.h@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: sql/ha_berkeley.h -> BitKeeper/deleted/.del-ha_berkeley.h

  BitKeeper/deleted/.del-mysqlmanager.c~e97636d71145a0b@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.47.3.2

  BitKeeper/deleted/.del-mysqlmanager.c~e97636d71145a0b@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: tools/mysqlmanager.c -> BitKeeper/deleted/.del-mysqlmanager.c~e97636d71145a0b

  client/mysqldump.c@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.214.1.43

  client/mysqltest.c@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -2
    Auto merged
    MERGE: 1.155.9.85

  extra/comp_err.c@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.23.1.3

  extra/yassl/include/openssl/ssl.h@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.14.1.7

  extra/yassl/src/ssl.cpp@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.16.1.10

  include/my_global.h@stripped, 2007-02-22 17:56:57+02:00, monty@stripped +0 -16
    manual merge (ignore changes from 5.0)
    MERGE: 1.96.1.40

  libmysql/libmysql.def@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.43.1.2

  mysys/base64.c@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.5.1.10

  mysys/mf_keycache.c@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -2
    Auto merged
    MERGE: 1.55.1.6

  mysys/my_getopt.c@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.55.1.7

  mysys/my_init.c@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -2
    Auto merged
    MERGE: 1.44.1.4

  mysys/my_thr_init.c@stripped, 2007-02-22 17:56:57+02:00, monty@stripped +0 -3
    manual merge
    MERGE: 1.31.1.10

  mysys/ptr_cmp.c@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.6.1.2

  server-tools/instance-manager/mysql_connection.cc@stripped, 2007-02-22 17:56:57+02:00, monty@stripped +1 -2
    manual merge
    MERGE: 1.14.1.5

  server-tools/instance-manager/mysqlmanager.cc@stripped, 2007-02-22 17:56:57+02:00, monty@stripped +0 -1
    manual merge
    MERGE: 1.17.1.3

  sql/filesort.cc@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -1
    Auto merged
    MERGE: 1.105.1.11

  sql/item.cc@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.113.1.137

  sql/item_timefunc.cc@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.100.1.41

  sql/mysqld.cc@stripped, 2007-02-22 17:56:57+02:00, monty@stripped +0 -1
    manual merge
    MERGE: 1.439.1.150

  sql/sql_acl.cc@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.128.1.89

  sql/sql_base.cc@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.235.1.131

  sql/sql_insert.cc@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.146.1.70

  sql/sql_prepare.cc@stripped, 2007-02-22 17:48:12+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.142.1.52

  sql/sql_select.cc@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -1
    Auto merged
    MERGE: 1.312.1.181

  sql/sql_show.cc@stripped, 2007-02-22 17:56:57+02:00, monty@stripped +3 -6
    manual merge
    MERGE: 1.253.1.88

  sql/unireg.cc@stripped, 2007-02-22 17:56:58+02:00, monty@stripped +0 -0
    no changes
    MERGE: 1.53.1.30

  storage/innobase/handler/ha_innodb.cc@stripped, 2007-02-22 17:56:58+02:00, monty@stripped +6 -9
    manual merge
    MERGE: 1.202.36.2

  storage/innobase/handler/ha_innodb.cc@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: sql/ha_innodb.cc -> storage/innobase/handler/ha_innodb.cc

  storage/innobase/include/ut0byte.ic@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.4.1.2

  storage/innobase/include/ut0byte.ic@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: innobase/include/ut0byte.ic -> storage/innobase/include/ut0byte.ic

  storage/innobase/include/ut0ut.ic@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.3.1.2

  storage/innobase/include/ut0ut.ic@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: innobase/include/ut0ut.ic -> storage/innobase/include/ut0ut.ic

  storage/myisam/mi_packrec.c@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.30.15.2

  storage/myisam/mi_packrec.c@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: myisam/mi_packrec.c -> storage/myisam/mi_packrec.c

  storage/myisam/myisamchk.c@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.112.11.2

  storage/myisam/myisamchk.c@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: myisam/myisamchk.c -> storage/myisam/myisamchk.c

  storage/ndb/include/kernel/signaldata/DictTabInfo.hpp@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -5
    Auto merged
    MERGE: 1.17.8.2

  storage/ndb/include/kernel/signaldata/DictTabInfo.hpp@stripped, 2007-02-22 17:48:11+02:00, monty@stripped +0 -0
    Merge rename: ndb/include/kernel/signaldata/DictTabInfo.hpp -> storage/ndb/include/kernel/signaldata/DictTabInfo.hpp

  strings/ctype-ucs2.c@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.50.1.15

  strings/ctype-utf8.c@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.97.1.8

  strings/decimal.c@stripped, 2007-02-22 17:48:13+02:00, monty@stripped +0 -0
    Auto merged
    MERGE: 1.65.1.12

  support-files/compiler_warnings.supp@stripped, 2007-02-22 17:56:58+02:00, monty@stripped +8 -8
    manual merge
    MERGE: 1.2.1.2

# 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:	monty
# Host:	narttu.mysql.fi
# Root:	/home/my/mysql-5.1/RESYNC

--- 1.266/client/mysqldump.c	2007-01-29 01:47:29 +02:00
+++ 1.267/client/mysqldump.c	2007-02-22 17:48:11 +02:00
@@ -2172,7 +2172,8 @@
 
 */
 
-static void dump_triggers_for_table(char *table, char *db)
+static void dump_triggers_for_table(char *table,
+                                    char *db __attribute__((unused)))
 {
   char       *result_table;
   char       name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
@@ -2181,7 +2182,6 @@
   FILE       *sql_file= md_result_file;
   MYSQL_RES  *result;
   MYSQL_ROW  row;
-
   DBUG_ENTER("dump_triggers_for_table");
   DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
 

--- 1.26/extra/comp_err.c	2006-12-23 21:19:44 +02:00
+++ 1.27/extra/comp_err.c	2007-02-22 17:48:11 +02:00
@@ -41,7 +41,9 @@
 static char *STATEFILE= (char*) "sql_state.h";
 static char *TXTFILE= (char*) "../sql/share/errmsg.txt";
 static char *DATADIRECTORY= (char*) "../sql/share/";
+#ifndef DBUG_OFF
 static char *default_dbug_option= (char*) "d:t:O,/tmp/comp_err.trace";
+#endif
 
 /* Header for errmsg.sys files */
 uchar file_head[]= { 254, 254, 2, 1 };
@@ -402,6 +404,8 @@
   int rcount= 0;
   DBUG_ENTER("parse_input_file");
 
+  *top_error= 0;
+  *top_lang= 0;
   if (!(file= my_fopen(file_name, O_RDONLY | O_SHARE, MYF(MY_WME))))
     DBUG_RETURN(0);
 

--- 1.30.15.1/myisam/mi_packrec.c	2007-02-22 16:59:54 +02:00
+++ 1.46/storage/myisam/mi_packrec.c	2007-02-22 17:48:13 +02:00
@@ -1481,56 +1481,33 @@
 static int _mi_read_mempack_record(MI_INFO *info,my_off_t filepos,byte *buf);
 static int _mi_read_rnd_mempack_record(MI_INFO*, byte *,my_off_t, my_bool);
 
-#ifndef MAP_NORESERVE
-#define MAP_NORESERVE 0		/* For irix */
-#endif
-#ifndef MAP_FAILED
-#define MAP_FAILED -1
-#endif
-
 my_bool _mi_memmap_file(MI_INFO *info)
 {
-  byte *file_map;
   MYISAM_SHARE *share=info->s;
   DBUG_ENTER("mi_memmap_file");
 
-  if (!share->file_map)
+  if (!info->s->file_map)
   {
-    my_off_t data_file_length= share->state.state.data_file_length;
-    if (data_file_length > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN)
-    {
-      DBUG_PRINT("warning", ("File is too large for mmap"));
-      DBUG_RETURN(0);
-    }
     if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
-        data_file_length + MEMMAP_EXTRA_MARGIN)
+        share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN)
     {
       DBUG_PRINT("warning",("File isn't extended for memmap"));
       DBUG_RETURN(0);
     }
-    file_map=(byte*)
-      my_mmap(0, (size_t) (data_file_length + MEMMAP_EXTRA_MARGIN), PROT_READ,
-              MAP_SHARED | MAP_NORESERVE, info->dfile, 0L);
-    if (file_map == (byte*) MAP_FAILED)
-    {
-      DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
-      my_errno=errno;
+    if (mi_dynmap_file(info, share->state.state.data_file_length))
       DBUG_RETURN(0);
-    }
-    share->file_map= file_map;
   }
   info->opt_flag|= MEMMAP_USED;
-  info->read_record=share->read_record=_mi_read_mempack_record;
-  share->read_rnd=_mi_read_rnd_mempack_record;
+  info->read_record= share->read_record= _mi_read_mempack_record;
+  share->read_rnd= _mi_read_rnd_mempack_record;
   DBUG_RETURN(1);
 }
 
 
 void _mi_unmap_file(MI_INFO *info)
 {
-  VOID(my_munmap(info->s->file_map,
-	      (size_t) info->s->state.state.data_file_length+
-	      MEMMAP_EXTRA_MARGIN));
+  VOID(my_munmap(info->s->file_map, 
+                 (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN));
 }
 
 

--- 1.112.11.1/myisam/myisamchk.c	2007-02-22 16:59:54 +02:00
+++ 1.125/storage/myisam/myisamchk.c	2007-02-22 17:48:13 +02:00
@@ -33,10 +33,6 @@
 #define my_raid_delete(A,B,C) my_delete(A,B)
 #endif
 
-#ifdef OS2
-#define _sanity(a,b)
-#endif
-
 static uint decode_bits;
 static char **default_argv;
 static const char *load_default_groups[]= { "myisamchk", 0 };
@@ -91,10 +87,6 @@
   MY_INIT(argv[0]);
   my_progname_short= my_progname+dirname_length(my_progname);
 
-#ifdef __EMX__
-  _wildcard (&argc, &argv);
-#endif
-
   myisamchk_init(&check_param);
   check_param.opt_lock_memory=1;		/* Lock memory if possible */
   check_param.using_global_keycache = 0;
@@ -377,7 +369,7 @@
                       directly with '--variable-name=value'.\n\
   -t, --tmpdir=path   Path for temporary files. Multiple paths can be\n\
                       specified, separated by ");
-#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
+#if defined( __WIN__) || defined(__NETWARE__)
    printf("semicolon (;)");
 #else
    printf("colon (:)");
@@ -704,6 +696,7 @@
   {
     int method;
     enum_mi_stats_method method_conv;
+    LINT_INIT(method_conv);
     myisam_stats_method_str= argument;
     if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
     {

--- 1.64/mysys/mf_keycache.c	2007-02-20 18:09:56 +02:00
+++ 1.65/mysys/mf_keycache.c	2007-02-22 17:48:12 +02:00
@@ -159,8 +159,10 @@
                                      struct st_my_thread_var *thread);
 #endif
 static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block);
+#ifndef DBUG_OFF
 static void test_key_cache(KEY_CACHE *keycache,
                            const char *where, my_bool lock);
+#endif
 
 #define KEYCACHE_HASH(f, pos)                                                 \
 (((ulong) ((pos) >> keycache->key_cache_shift)+                               \

--- 1.8/mysys/ptr_cmp.c	2006-12-23 21:19:47 +02:00
+++ 1.9/mysys/ptr_cmp.c	2007-02-22 17:48:12 +02:00
@@ -185,7 +185,7 @@
   case 3: pos= (my_off_t) mi_uint3korr(ptr); break;
   case 2: pos= (my_off_t) mi_uint2korr(ptr); break;
   case 1: pos= (my_off_t) *(uchar*) ptr; break;
-  default: DBUG_ASSERT(0);
+  default: DBUG_ASSERT(0); return 0;
   }
  return pos;
 }

--- 1.151.8.1/sql/ha_berkeley.cc	2007-02-22 16:59:55 +02:00
+++ 1.187/BitKeeper/deleted/.del-ha_berkeley.cc	2007-02-22 17:48:11 +02:00
@@ -24,7 +24,8 @@
     We will need an updated Berkeley DB version for this.
   - Killing threads that has got a 'deadlock'
   - SHOW TABLE STATUS should give more information about the table.
-  - Get a more accurate count of the number of rows (estimate_rows_upper_bound()).
+  - Get a more accurate count of the number of rows
+    (estimate_rows_upper_bound()).
     We could store the found number of rows when the table is scanned and
     then increment the counter for each attempted write.
   - We will need to extend the manager thread to makes checkpoints at
@@ -52,14 +53,17 @@
 
 #include "mysql_priv.h"
 
-#ifdef HAVE_BERKELEY_DB
 #include <m_ctype.h>
 #include <myisampack.h>
 #include <hash.h>
+
+#ifdef WITH_BERKELEY_STORAGE_ENGINE
 #include "ha_berkeley.h"
 #include "sql_manager.h"
 #include <stdarg.h>
 
+#include <mysql/plugin.h>
+
 #define HA_BERKELEY_ROWS_IN_TABLE 10000 /* to get optimization right */
 #define HA_BERKELEY_RANGE_COUNT   100
 #define HA_BERKELEY_MAX_ROWS	  10000000 /* Max rows in table */
@@ -71,13 +75,21 @@
 #define STATUS_ROW_COUNT_INIT	2
 #define STATUS_BDB_ANALYZE	4
 
+const u_int32_t bdb_DB_TXN_NOSYNC= DB_TXN_NOSYNC;
+const u_int32_t bdb_DB_RECOVER= DB_RECOVER;
+const u_int32_t bdb_DB_PRIVATE= DB_PRIVATE;
+const u_int32_t bdb_DB_DIRECT_DB= DB_DIRECT_DB;
+const u_int32_t bdb_DB_DIRECT_LOG= DB_DIRECT_LOG;
 const char *ha_berkeley_ext=".db";
 bool berkeley_shared_data=0;
-u_int32_t berkeley_init_flags= DB_PRIVATE | DB_RECOVER, berkeley_env_flags=0,
-          berkeley_lock_type=DB_LOCK_DEFAULT;
-ulong berkeley_cache_size, berkeley_log_buffer_size, berkeley_log_file_size=0;
+u_int32_t berkeley_init_flags= DB_PRIVATE | DB_RECOVER,
+          berkeley_env_flags= DB_LOG_AUTOREMOVE,
+          berkeley_lock_type= DB_LOCK_DEFAULT;
+ulong berkeley_log_buffer_size=0 , berkeley_log_file_size=0;
+ulonglong berkeley_cache_size= 0;
 char *berkeley_home, *berkeley_tmpdir, *berkeley_logdir;
 long berkeley_lock_scan_time=0;
+ulong berkeley_region_size=0, berkeley_cache_parts=1;
 ulong berkeley_trans_retry=1;
 ulong berkeley_max_lock;
 pthread_mutex_t bdb_mutex;
@@ -85,14 +97,21 @@
 static DB_ENV *db_env;
 static HASH bdb_open_tables;
 
+static const char berkeley_hton_name[]= "BerkeleyDB";
+static const int berkeley_hton_name_length=sizeof(berkeley_hton_name)-1;
+
 const char *berkeley_lock_names[] =
-{ "DEFAULT", "OLDEST","RANDOM","YOUNGEST",0 };
+{ "DEFAULT", "OLDEST", "RANDOM", "YOUNGEST", "EXPIRE", "MAXLOCKS",
+  "MAXWRITE", "MINLOCKS", "MINWRITE", 0 };
 u_int32_t berkeley_lock_types[]=
-{ DB_LOCK_DEFAULT, DB_LOCK_OLDEST, DB_LOCK_RANDOM };
+{ DB_LOCK_DEFAULT, DB_LOCK_OLDEST, DB_LOCK_RANDOM, DB_LOCK_YOUNGEST,
+  DB_LOCK_EXPIRE, DB_LOCK_MAXLOCKS, DB_LOCK_MAXWRITE, DB_LOCK_MINLOCKS,
+  DB_LOCK_MINWRITE };
 TYPELIB berkeley_lock_typelib= {array_elements(berkeley_lock_names)-1,"",
 				berkeley_lock_names, NULL};
 
-static void berkeley_print_error(const char *db_errpfx, char *buffer);
+static void berkeley_print_error(const DB_ENV *db_env, const char *db_errpfx,
+                                 const char *buffer);
 static byte* bdb_get_key(BDB_SHARE *share,uint *length,
 			 my_bool not_used __attribute__((unused)));
 static BDB_SHARE *get_share(const char *table_name, TABLE *table);
@@ -100,50 +119,53 @@
 		      bool mutex_is_locked);
 static int write_status(DB *status_block, char *buff, uint length);
 static void update_status(BDB_SHARE *share, TABLE *table);
-static void berkeley_noticecall(DB_ENV *db_env, db_notices notice);
 
 static int berkeley_close_connection(THD *thd);
 static int berkeley_commit(THD *thd, bool all);
 static int berkeley_rollback(THD *thd, bool all);
+static int berkeley_rollback_to_savepoint(THD* thd, void *savepoint);
+static int berkeley_savepoint(THD* thd, void *savepoint);
+static int berkeley_release_savepoint(THD* thd, void *savepoint);
+static handler *berkeley_create_handler(TABLE_SHARE *table,
+                                        MEM_ROOT *mem_root);
 
-handlerton berkeley_hton = {
-  "BerkeleyDB",
-  SHOW_OPTION_YES,
-  "Supports transactions and page-level locking", 
-  DB_TYPE_BERKELEY_DB,
-  berkeley_init,
-  0, /* slot */
-  0, /* savepoint size */
-  berkeley_close_connection,
-  NULL, /* savepoint_set */
-  NULL, /* savepoint_rollback */
-  NULL, /* savepoint_release */
-  berkeley_commit,
-  berkeley_rollback,
-  NULL, /* prepare */
-  NULL, /* recover */
-  NULL, /* commit_by_xid */
-  NULL, /* rollback_by_xid */
-  NULL, /* create_cursor_read_view */
-  NULL, /* set_cursor_read_view */
-  NULL, /* close_cursor_read_view */
-  HTON_CLOSE_CURSORS_AT_COMMIT
-};
+handlerton berkeley_hton;
+
+static handler *berkeley_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
+{
+  return new (mem_root) ha_berkeley(table);
+}
 
 typedef struct st_berkeley_trx_data {
   DB_TXN *all;
   DB_TXN *stmt;
+  DB_TXN *sp_level;
   uint bdb_lock_count;
 } berkeley_trx_data;
 
 /* General functions */
 
-bool berkeley_init(void)
+int berkeley_init(void)
 {
   DBUG_ENTER("berkeley_init");
 
+  berkeley_hton.state=SHOW_OPTION_YES;
+  berkeley_hton.db_type=DB_TYPE_BERKELEY_DB;
+  berkeley_hton.savepoint_offset=sizeof(DB_TXN *);
+  berkeley_hton.close_connection=berkeley_close_connection;
+  berkeley_hton.savepoint_set=berkeley_savepoint;
+  berkeley_hton.savepoint_rollback=berkeley_rollback_to_savepoint;
+  berkeley_hton.savepoint_release=berkeley_release_savepoint;
+  berkeley_hton.commit=berkeley_commit;
+  berkeley_hton.rollback=berkeley_rollback;
+  berkeley_hton.create=berkeley_create_handler;
+  berkeley_hton.panic=berkeley_end;
+  berkeley_hton.flush_logs=berkeley_flush_logs;
+  berkeley_hton.show_status=berkeley_show_status;
+  berkeley_hton.flags=HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME;
+
   if (have_berkeley_db != SHOW_OPTION_YES)
-    goto error;
+    return 0; // nothing else to do
 
   if (!berkeley_tmpdir)
     berkeley_tmpdir=mysql_tmpdir;
@@ -173,7 +195,6 @@
     goto error;
   db_env->set_errcall(db_env,berkeley_print_error);
   db_env->set_errpfx(db_env,"bdb");
-  db_env->set_noticecall(db_env, berkeley_noticecall);
   db_env->set_tmp_dir(db_env, berkeley_tmpdir);
   db_env->set_data_dir(db_env, mysql_data_home);
   db_env->set_flags(db_env, berkeley_env_flags, 1);
@@ -182,13 +203,20 @@
 
   if (opt_endinfo)
     db_env->set_verbose(db_env,
-			DB_VERB_CHKPOINT | DB_VERB_DEADLOCK | DB_VERB_RECOVERY,
+			DB_VERB_DEADLOCK | DB_VERB_RECOVERY,
 			1);
 
-  db_env->set_cachesize(db_env, 0, berkeley_cache_size, 0);
+  if (berkeley_cache_size > (uint) ~0)
+    db_env->set_cachesize(db_env, berkeley_cache_size / (1024*1024L*1024L),
+                          berkeley_cache_size % (1024L*1024L*1024L),
+                          berkeley_cache_parts);
+  else
+    db_env->set_cachesize(db_env, 0, berkeley_cache_size, berkeley_cache_parts);
+
   db_env->set_lg_max(db_env, berkeley_log_file_size);
   db_env->set_lg_bsize(db_env, berkeley_log_buffer_size);
   db_env->set_lk_detect(db_env, berkeley_lock_type);
+  db_env->set_lg_regionmax(db_env, berkeley_region_size);
   if (berkeley_max_lock)
     db_env->set_lk_max(db_env, berkeley_max_lock);
 
@@ -213,18 +241,19 @@
 }
 
 
-bool berkeley_end(void)
+int berkeley_end(ha_panic_function type)
 {
-  int error;
+  int error= 0;
   DBUG_ENTER("berkeley_end");
-  if (!db_env)
-    return 1; /* purecov: tested */
-  berkeley_cleanup_log_files();
-  error=db_env->close(db_env,0);		// Error is logged
-  db_env=0;
-  hash_free(&bdb_open_tables);
-  pthread_mutex_destroy(&bdb_mutex);
-  DBUG_RETURN(error != 0);
+  if (db_env)
+  {
+    berkeley_cleanup_log_files();
+    error= db_env->close(db_env,0);		// Error is logged
+    db_env= 0;
+    hash_free(&bdb_open_tables);
+    pthread_mutex_destroy(&bdb_mutex);
+  }
+  DBUG_RETURN(error);
 }
 
 static int berkeley_close_connection(THD *thd)
@@ -258,7 +287,7 @@
   DBUG_PRINT("trans",("ending transaction %s", all ? "all" : "stmt"));
   berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
   DB_TXN **txn= all ? &trx->all : &trx->stmt;
-  int error=txn_commit(*txn,0);
+  int error= (*txn)->commit(*txn,0);
   *txn=0;
 #ifndef DBUG_OFF
   if (error)
@@ -273,13 +302,55 @@
   DBUG_PRINT("trans",("aborting transaction %s", all ? "all" : "stmt"));
   berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
   DB_TXN **txn= all ? &trx->all : &trx->stmt;
-  int error=txn_abort(*txn);
+  int error= (*txn)->abort(*txn);
   *txn=0;
   DBUG_RETURN(error);
 }
 
+static int berkeley_savepoint(THD* thd, void *savepoint)
+{
+  int error;
+  DB_TXN **save_txn= (DB_TXN**) savepoint;
+  DBUG_ENTER("berkeley_savepoint");
+  berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+  if (!(error= db_env->txn_begin(db_env, trx->sp_level, save_txn, 0)))
+  {
+    trx->sp_level= *save_txn;
+  }
+  DBUG_RETURN(error);
+}
+
+static int berkeley_rollback_to_savepoint(THD* thd, void *savepoint)
+{
+  int error;
+  DB_TXN *parent, **save_txn= (DB_TXN**) savepoint;
+  DBUG_ENTER("berkeley_rollback_to_savepoint");
+  berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+  parent= (*save_txn)->parent;
+  if (!(error= (*save_txn)->abort(*save_txn)))
+  {
+    trx->sp_level= parent;
+    error= berkeley_savepoint(thd, savepoint);
+  }
+  DBUG_RETURN(error);
+}
 
-int berkeley_show_logs(Protocol *protocol)
+static int berkeley_release_savepoint(THD* thd, void *savepoint)
+{
+  int error;
+  DB_TXN *parent, **save_txn= (DB_TXN**) savepoint;
+  DBUG_ENTER("berkeley_release_savepoint");
+  berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+  parent= (*save_txn)->parent;
+  if (!(error= (*save_txn)->commit(*save_txn,0)))
+  {
+    trx->sp_level= parent;
+    *save_txn= 0;
+  }
+  DBUG_RETURN(error);
+}
+
+static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print)
 {
   char **all_logs, **free_logs, **a, **f;
   int error=1;
@@ -290,6 +361,7 @@
   init_sql_alloc(&show_logs_root, BDB_LOG_ALLOC_BLOCK_SIZE,
 		 BDB_LOG_ALLOC_BLOCK_SIZE);
   *root_ptr= &show_logs_root;
+  all_logs= free_logs= 0;
 
   if ((error= db_env->log_archive(db_env, &all_logs,
 				  DB_ARCH_ABS | DB_ARCH_LOG)) ||
@@ -306,50 +378,51 @@
   {
     for (a = all_logs, f = free_logs; *a; ++a)
     {
-      protocol->prepare_for_resend();
-      protocol->store(*a, system_charset_info);
-      protocol->store(STRING_WITH_LEN("BDB"), system_charset_info);
       if (f && *f && strcmp(*a, *f) == 0)
       {
-	f++;
-	protocol->store(SHOW_LOG_STATUS_FREE, system_charset_info);
+        f++;
+        if ((error= stat_print(thd, berkeley_hton_name,
+                               berkeley_hton_name_length, *a, strlen(*a),
+                               STRING_WITH_LEN(SHOW_LOG_STATUS_FREE))))
+          break;
       }
       else
-	protocol->store(SHOW_LOG_STATUS_INUSE, system_charset_info);
-
-      if (protocol->write())
       {
-	error=1;
-	goto err;
+        if ((error= stat_print(thd, berkeley_hton_name,
+                               berkeley_hton_name_length, *a, strlen(*a),
+                               STRING_WITH_LEN(SHOW_LOG_STATUS_INUSE))))
+          break;
       }
     }
   }
 err:
+  if (all_logs)
+    free(all_logs);
+  if (free_logs)
+    free(free_logs);
   free_root(&show_logs_root,MYF(0));
   *root_ptr= old_mem_root;
   DBUG_RETURN(error);
 }
 
-
-static void berkeley_print_error(const char *db_errpfx, char *buffer)
+bool berkeley_show_status(THD *thd, stat_print_fn *stat_print,
+                          enum ha_stat_type stat_type)
 {
-  sql_print_error("%s:  %s",db_errpfx,buffer); /* purecov: tested */
+  switch (stat_type) {
+  case HA_ENGINE_LOGS:
+    return berkeley_show_logs(thd, stat_print);
+  default:
+    return FALSE;
+  }
 }
 
-
-static void berkeley_noticecall(DB_ENV *db_env, db_notices notice)
+static void berkeley_print_error(const DB_ENV *db_env, const char *db_errpfx,
+                                 const char *buffer)
 {
-  switch (notice)
-  {
-  case DB_NOTICE_LOGFILE_CHANGED: /* purecov: tested */
-    pthread_mutex_lock(&LOCK_manager);
-    manager_status |= MANAGER_BERKELEY_LOG_CLEANUP;
-    pthread_mutex_unlock(&LOCK_manager);
-    pthread_cond_signal(&COND_manager);
-    break;
-  }
+  sql_print_error("%s:  %s",db_errpfx,buffer); /* purecov: tested */
 }
 
+
 void berkeley_cleanup_log_files(void)
 {
   DBUG_ENTER("berkeley_cleanup_log_files");
@@ -387,10 +460,10 @@
 ** Berkeley DB tables
 *****************************************************************************/
 
-ha_berkeley::ha_berkeley(TABLE *table_arg)
+ha_berkeley::ha_berkeley(TABLE_SHARE *table_arg)
   :handler(&berkeley_hton, table_arg), alloc_ptr(0), rec_buff(0), file(0),
   int_table_flags(HA_REC_NOT_IN_SEQ | HA_FAST_KEY_READ |
-                  HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_NOT_EXACT_COUNT |
+                  HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS |
                   HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED |
                   HA_CAN_GEOMETRY |
                   HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX),
@@ -414,13 +487,14 @@
                 | HA_READ_RANGE);
   for (uint i= all_parts ? 0 : part ; i <= part ; i++)
   {
-    if (table->key_info[idx].key_part[i].field->type() == FIELD_TYPE_BLOB)
+    KEY_PART_INFO *key_part= table_share->key_info[idx].key_part+i;
+    if (key_part->field->type() == FIELD_TYPE_BLOB)
     {
       /* We can't use BLOBS to shortcut sorts */
       flags&= ~(HA_READ_ORDER | HA_KEYREAD_ONLY | HA_READ_RANGE);
       break;
     }
-    switch (table->key_info[idx].key_part[i].field->key_type()) {
+    switch (key_part->field->key_type()) {
     case HA_KEYTYPE_TEXT:
     case HA_KEYTYPE_VARTEXT1:
     case HA_KEYTYPE_VARTEXT2:
@@ -428,8 +502,7 @@
         As BDB stores only one copy of equal strings, we can't use key read
         on these. Binary collations do support key read though.
       */
-      if (!(table->key_info[idx].key_part[i].field->charset()->state
-           & MY_CS_BINSORT))
+      if (!(key_part->field->charset()->state & MY_CS_BINSORT))
         flags&= ~HA_KEYREAD_ONLY;
       break;
     default:                                    // Keep compiler happy
@@ -567,7 +640,6 @@
   uint open_mode=(mode == O_RDONLY ? DB_RDONLY : 0) | DB_THREAD;
   uint max_key_length;
   int error;
-  TABLE_SHARE *table_share= table->s;
   DBUG_ENTER("ha_berkeley::open");
 
   /* Open primary key */
@@ -589,7 +661,7 @@
 			&key_buff2, max_key_length,
 			&primary_key_buff,
 			(hidden_primary_key ? 0 :
-			 table->key_info[table_share->primary_key].key_length),
+			 table_share->key_info[table_share->primary_key].key_length),
 			NullS)))
     DBUG_RETURN(1); /* purecov: inspected */
   if (!(rec_buff= (byte*) my_malloc((alloced_rec_buff_length=
@@ -632,10 +704,10 @@
 			  berkeley_cmp_packed_key));
     if (!hidden_primary_key)
       file->app_private= (void*) (table->key_info + table_share->primary_key);
-    if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
+    if ((error= db_env->txn_begin(db_env, NULL, (DB_TXN**) &transaction, 0)) ||
 	(error= (file->open(file, transaction,
 			    fn_format(name_buff, name, "", ha_berkeley_ext,
-				      2 | 4),
+				      MY_UNPACK_FILENAME|MY_APPEND_EXT),
 			    "main", DB_BTREE, open_mode, 0))) ||
 	(error= transaction->commit(transaction, 0)))
     {
@@ -648,7 +720,7 @@
 
     /* Open other keys;  These are part of the share structure */
     key_file[primary_key]=file;
-    key_type[primary_key]=DB_NOOVERWRITE;
+    key_type[primary_key]= hidden_primary_key ? 0 : DB_NOOVERWRITE;
 
     DB **ptr=key_file;
     for (uint i=0, used_keys=0; i < table_share->keys ; i++, ptr++)
@@ -671,7 +743,8 @@
 	  DBUG_PRINT("bdb",("Setting DB_DUP for key %u", i));
 	  (*ptr)->set_flags(*ptr, DB_DUP);
 	}
-	if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
+	if ((error= db_env->txn_begin(db_env, NULL, (DB_TXN**) &transaction,
+                                      0)) ||
 	    (error=((*ptr)->open(*ptr, transaction, name_buff, part, DB_BTREE,
 				 open_mode, 0))) ||
 	    (error= transaction->commit(transaction, 0)))
@@ -703,7 +776,7 @@
   transaction=0;
   cursor=0;
   key_read=0;
-  block_size=8192;				// Berkeley DB block size
+  stats.block_size=8192;                        // Berkeley DB block size
   share->fixed_length_row= !(table_share->db_create_options &
                              HA_OPTION_PACK_RECORD);
 
@@ -719,7 +792,7 @@
 
   my_free((char*) rec_buff,MYF(MY_ALLOW_ZERO_PTR));
   my_free(alloc_ptr,MYF(MY_ALLOW_ZERO_PTR));
-  ha_berkeley::extra(HA_EXTRA_RESET);		// current_row buffer
+  ha_berkeley::reset();                         // current_row buffer
   DBUG_RETURN(free_share(share,table, hidden_primary_key,0));
 }
 
@@ -745,9 +818,9 @@
 
 ulong ha_berkeley::max_row_length(const byte *buf)
 {
-  ulong length= table->s->reclength + table->s->fields*2;
+  ulong length= table_share->reclength + table_share->fields*2;
   uint *ptr, *end;
-  for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+  for (ptr= table_share->blob_field, end=ptr + table_share->blob_fields ;
        ptr != end ;
        ptr++)
   {
@@ -774,25 +847,26 @@
   if (share->fixed_length_row)
   {
     row->data=(void*) record;
-    row->size= table->s->reclength+hidden_primary_key;
+    row->size= table_share->reclength+hidden_primary_key;
     if (hidden_primary_key)
     {
       if (new_row)
 	get_auto_primary_key(current_ident);
-      memcpy_fixed((char*) record+table->s->reclength, (char*) current_ident,
+      memcpy_fixed((char*) record+table_share->reclength,
+                   (char*) current_ident,
 		   BDB_HIDDEN_PRIMARY_KEY_LENGTH);
     }
     return 0;
   }
-  if (table->s->blob_fields)
+  if (table_share->blob_fields)
   {
     if (fix_rec_buff_for_blob(max_row_length(record)))
       return HA_ERR_OUT_OF_MEM; /* purecov: inspected */
   }
 
   /* Copy null bits */
-  memcpy(rec_buff, record, table->s->null_bytes);
-  ptr= rec_buff + table->s->null_bytes;
+  memcpy(rec_buff, record, table_share->null_bytes);
+  ptr= rec_buff + table_share->null_bytes;
 
   for (Field **field=table->field ; *field ; field++)
     ptr=(byte*) (*field)->pack((char*) ptr,
@@ -815,15 +889,17 @@
 void ha_berkeley::unpack_row(char *record, DBT *row)
 {
   if (share->fixed_length_row)
-    memcpy(record,(char*) row->data,table->s->reclength+hidden_primary_key);
+    memcpy(record,(char*) row->data,table_share->reclength+hidden_primary_key);
   else
   {
     /* Copy null bits */
+    my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
     const char *ptr= (const char*) row->data;
-    memcpy(record, ptr, table->s->null_bytes);
-    ptr+= table->s->null_bytes;
+    memcpy(record, ptr, table_share->null_bytes);
+    ptr+= table_share->null_bytes;
     for (Field **field=table->field ; *field ; field++)
       ptr= (*field)->unpack(record + (*field)->offset(), ptr);
+    dbug_tmp_restore_column_map(table->write_set, old_map);
   }
 }
 
@@ -881,6 +957,7 @@
   KEY *key_info=table->key_info+keynr;
   KEY_PART_INFO *key_part=key_info->key_part;
   KEY_PART_INFO *end=key_part+key_info->key_parts;
+  my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
   DBUG_ENTER("create_key");
 
   key->data=buff;
@@ -904,6 +981,7 @@
   }
   key->size= (buff  - (char*) key->data);
   DBUG_DUMP("key",(char*) key->data, key->size);
+  dbug_tmp_restore_column_map(table->write_set, old_map);
   DBUG_RETURN(key);
 }
 
@@ -921,6 +999,7 @@
   KEY *key_info=table->key_info+keynr;
   KEY_PART_INFO *key_part=key_info->key_part;
   KEY_PART_INFO *end=key_part+key_info->key_parts;
+  my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
   DBUG_ENTER("bdb:pack_key");
 
   bzero((char*) key,sizeof(*key));
@@ -948,6 +1027,7 @@
   }
   key->size= (buff  - (char*) key->data);
   DBUG_DUMP("key",(char*) key->data, key->size);
+  dbug_tmp_restore_column_map(table->write_set, old_map);
   DBUG_RETURN(key);
 }
 
@@ -970,7 +1050,7 @@
     DBUG_RETURN(error); /* purecov: inspected */
 
   table->insert_or_update= 1;                   // For handling of VARCHAR
-  if (table->s->keys + test(hidden_primary_key) == 1)
+  if (table_share->keys + test(hidden_primary_key) == 1)
   {
     error=file->put(file, transaction, create_key(&prim_key, primary_key,
 						  key_buff, record),
@@ -989,7 +1069,7 @@
 			    &row, key_type[primary_key])))
       {
 	changed_keys.set_bit(primary_key);
-	for (uint keynr=0 ; keynr < table->s->keys ; keynr++)
+	for (uint keynr=0 ; keynr < table_share->keys ; keynr++)
 	{
 	  if (keynr == primary_key)
 	    continue;
@@ -1017,7 +1097,7 @@
 	  {
 	    new_error = 0;
 	    for (uint keynr=0;
-                 keynr < table->s->keys+test(hidden_primary_key);
+                 keynr < table_share->keys+test(hidden_primary_key);
                  keynr++)
 	    {
 	      if (changed_keys.is_set(keynr))
@@ -1160,7 +1240,7 @@
      that one just put back the old value. */
   if (!changed_keys->is_clear_all())
   {
-    for (keynr=0 ; keynr < table->s->keys+test(hidden_primary_key) ; keynr++)
+    for (keynr=0 ; keynr < table_share->keys+test(hidden_primary_key) ; keynr++)
     {
       if (changed_keys->is_set(keynr))
       {
@@ -1189,8 +1269,8 @@
   DB_TXN *sub_trans;
   bool primary_key_changed;
   DBUG_ENTER("update_row");
-  LINT_INIT(error);
 
+  LINT_INIT(error);
   statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
     table->timestamp_field->set_time();
@@ -1225,7 +1305,7 @@
 				   using_ignore)))
     {
       // Update all other keys
-      for (uint keynr=0 ; keynr < table->s->keys ; keynr++)
+      for (uint keynr=0 ; keynr < table_share->keys ; keynr++)
       {
 	if (keynr == primary_key)
 	  continue;
@@ -1337,7 +1417,7 @@
 {
   int result = 0;
   for (uint keynr=0;
-       keynr < table->s->keys+test(hidden_primary_key);
+       keynr < table_share->keys+test(hidden_primary_key);
        keynr++)
   {
     if (keys->is_set(keynr))
@@ -1358,7 +1438,7 @@
 {
   int error;
   DBT row, prim_key;
-  key_map keys= table->s->keys_in_use;
+  key_map keys= table_share->keys_in_use;
   DBUG_ENTER("delete_row");
   statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
 
@@ -1390,11 +1470,12 @@
 }
 
 
-int ha_berkeley::index_init(uint keynr)
+int ha_berkeley::index_init(uint keynr, bool sorted)
 {
   int error;
   DBUG_ENTER("ha_berkeley::index_init");
-  DBUG_PRINT("enter",("table: '%s'  key: %d", table->s->table_name, keynr));
+  DBUG_PRINT("enter",("table: '%s'  key: %d", table_share->table_name.str,
+                      keynr));
 
   /*
     Under some very rare conditions (like full joins) we may already have
@@ -1421,7 +1502,7 @@
   DBUG_ENTER("ha_berkely::index_end");
   if (cursor)
   {
-    DBUG_PRINT("enter",("table: '%s'", table->s->table_name));
+    DBUG_PRINT("enter",("table: '%s'", table_share->table_name.str));
     error=cursor->c_close(cursor);
     cursor=0;
   }
@@ -1668,7 +1749,7 @@
 {
   DBUG_ENTER("rnd_init");
   current_row.flags=DB_DBT_REALLOC;
-  DBUG_RETURN(index_init(primary_key));
+  DBUG_RETURN(index_init(primary_key, 0));
 }
 
 int ha_berkeley::rnd_end()
@@ -1770,20 +1851,21 @@
   DBUG_ENTER("ha_berkeley::info");
   if (flag & HA_STATUS_VARIABLE)
   {
-    records = share->rows + changed_rows; // Just to get optimisations right
-    deleted = 0;
+    // Just to get optimizations right
+    stats.records = share->rows + changed_rows;
+    stats.deleted = 0;
   }
   if ((flag & HA_STATUS_CONST) || version != share->version)
   {
     version=share->version;
-    for (uint i=0 ; i < table->s->keys ; i++)
+    for (uint i=0 ; i < table_share->keys ; i++)
     {
       table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]=
 	share->rec_per_key[i];
     }
   }
   /* Don't return key if we got an error for the internal primary key */
-  if (flag & HA_STATUS_ERRKEY && last_dup_key < table->s->keys)
+  if (flag & HA_STATUS_ERRKEY && last_dup_key < table_share->keys)
     errkey= last_dup_key;
   DBUG_RETURN(0);
 }
@@ -1792,19 +1874,8 @@
 int ha_berkeley::extra(enum ha_extra_function operation)
 {
   switch (operation) {
-  case HA_EXTRA_RESET:
   case HA_EXTRA_RESET_STATE:
-    key_read=0;
-    using_ignore=0;
-    if (current_row.flags & (DB_DBT_MALLOC | DB_DBT_REALLOC))
-    {
-      current_row.flags=0;
-      if (current_row.data)
-      {
-	free(current_row.data);
-	current_row.data=0;
-      }
-    }
+    reset();
     break;
   case HA_EXTRA_KEYREAD:
     key_read=1;					// Query satisfied with key
@@ -1827,8 +1898,17 @@
 
 int ha_berkeley::reset(void)
 {
-  ha_berkeley::extra(HA_EXTRA_RESET);
-  key_read=0;					// Reset to state after open
+  key_read= 0;
+  using_ignore= 0;
+  if (current_row.flags & (DB_DBT_MALLOC | DB_DBT_REALLOC))
+  {
+    current_row.flags= 0;
+    if (current_row.data)
+    {
+      free(current_row.data);
+      current_row.data= 0;
+    }
+  }
   return 0;
 }
 
@@ -1854,6 +1934,8 @@
     if (!trx)
       DBUG_RETURN(1);
   }
+  if (trx->all == 0)
+    trx->sp_level= 0;
   if (lock_type != F_UNLCK)
   {
     if (!trx->bdb_lock_count++)
@@ -1867,17 +1949,18 @@
 	/* We have to start a master transaction */
 	DBUG_PRINT("trans",("starting transaction all:  options: 0x%lx",
                             (ulong) thd->options));
-        if ((error=txn_begin(db_env, 0, &trx->all, 0)))
+        if ((error= db_env->txn_begin(db_env, NULL, &trx->all, 0)))
 	{
           trx->bdb_lock_count--;        // We didn't get the lock
           DBUG_RETURN(error);
 	}
+        trx->sp_level= trx->all;
         trans_register_ha(thd, TRUE, &berkeley_hton);
 	if (thd->in_lock_tables)
 	  DBUG_RETURN(0);			// Don't create stmt trans
       }
       DBUG_PRINT("trans",("starting transaction stmt"));
-      if ((error=txn_begin(db_env, trx->all, &trx->stmt, 0)))
+      if ((error= db_env->txn_begin(db_env, trx->sp_level, &trx->stmt, 0)))
       {
 	/* We leave the possible master transaction open */
         trx->bdb_lock_count--;                  // We didn't get the lock
@@ -1902,7 +1985,7 @@
 	   We must in this case commit the work to keep the row locks
 	*/
 	DBUG_PRINT("trans",("commiting non-updating transaction"));
-        error= txn_commit(trx->stmt,0);
+        error= trx->stmt->commit(trx->stmt,0);
         trx->stmt= transaction= 0;
       }
     }
@@ -1931,7 +2014,7 @@
   if (!trx->stmt)
   {
     DBUG_PRINT("trans",("starting transaction stmt"));
-    error=txn_begin(db_env, trx->all, &trx->stmt, 0);
+    error= db_env->txn_begin(db_env, trx->sp_level, &trx->stmt, 0);
     trans_register_ha(thd, FALSE, &berkeley_hton);
   }
   transaction= trx->stmt;
@@ -2026,13 +2109,14 @@
   int error;
   DBUG_ENTER("ha_berkeley::create");
 
-  fn_format(name_buff,name,"", ha_berkeley_ext,2 | 4);
+  fn_format(name_buff,name,"", ha_berkeley_ext,
+            MY_UNPACK_FILENAME|MY_APPEND_EXT);
 
   /* Create the main table that will hold the real rows */
   if ((error= create_sub_table(name_buff,"main",DB_BTREE,0)))
     DBUG_RETURN(error); /* purecov: inspected */
 
-  primary_key= table->s->primary_key;
+  primary_key= form->s->primary_key;
   /* Create the keys */
   for (uint i=0; i < form->s->keys; i++)
   {
@@ -2040,7 +2124,7 @@
     {
       sprintf(part,"key%02d",index++);
       if ((error= create_sub_table(name_buff, part, DB_BTREE,
-				   (table->key_info[i].flags & HA_NOSAME) ? 0 :
+				   (form->key_info[i].flags & HA_NOSAME) ? 0 :
 				   DB_DUP)))
 	DBUG_RETURN(error); /* purecov: inspected */
     }
@@ -2056,7 +2140,7 @@
 				    "status", DB_BTREE, DB_CREATE, 0))))
     {
       char rec_buff[4+MAX_KEY*4];
-      uint length= 4+ table->s->keys*4;
+      uint length= 4+ form->s->keys*4;
       bzero(rec_buff, length);
       error= write_status(status_block, rec_buff, length);
       status_block->close(status_block,0);
@@ -2075,8 +2159,9 @@
   if ((error=db_create(&file, db_env, 0)))
     my_errno=error; /* purecov: inspected */
   else
-    error=file->remove(file,fn_format(name_buff,name,"",ha_berkeley_ext,2 | 4),
-		       NULL,0);
+    error=file->remove(file,fn_format(name_buff,name,"",ha_berkeley_ext,
+                                      MY_UNPACK_FILENAME|MY_APPEND_EXT),
+                       NULL,0);
   file=0;					// Safety
   DBUG_RETURN(error);
 }
@@ -2094,9 +2179,11 @@
   {
     /* On should not do a file->close() after rename returns */
     error= file->rename(file, 
-			fn_format(from_buff, from, "", ha_berkeley_ext, 2 | 4),
+			fn_format(from_buff, from, "", 
+                                  ha_berkeley_ext,
+                                  MY_UNPACK_FILENAME|MY_APPEND_EXT),
 			NULL, fn_format(to_buff, to, "", ha_berkeley_ext,
-					2 | 4), 0);
+                                        MY_UNPACK_FILENAME|MY_APPEND_EXT), 0);
   }
   return error;
 }
@@ -2110,7 +2197,7 @@
 
 double ha_berkeley::scan_time()
 {
-  return rows2double(records/3);
+  return rows2double(stats.records/3);
 }
 
 ha_rows ha_berkeley::records_in_range(uint keynr, key_range *start_key,
@@ -2163,27 +2250,40 @@
     end_pos=end_range.less;
   else
     end_pos=end_range.less+end_range.equal;
-  rows=(end_pos-start_pos)*records;
+  rows=(end_pos-start_pos)*stats.records;
   DBUG_PRINT("exit",("rows: %g",rows));
   DBUG_RETURN((ha_rows)(rows <= 1.0 ? 1 : rows));
 }
 
 
-ulonglong ha_berkeley::get_auto_increment()
+void ha_berkeley::get_auto_increment(ulonglong offset, ulonglong increment,
+                                     ulonglong nb_desired_values,
+                                     ulonglong *first_value,
+                                     ulonglong *nb_reserved_values)
 {
+  /* Ideally in case of real error (not "empty table") nr should be ~ULL(0) */
   ulonglong nr=1;				// Default if error or new key
   int error;
   (void) ha_berkeley::extra(HA_EXTRA_KEYREAD);
 
   /* Set 'active_index' */
-  ha_berkeley::index_init(table->s->next_number_index);
+  ha_berkeley::index_init(table_share->next_number_index, 0);
 
-  if (!table->s->next_number_key_offset)
+  if (!table_share->next_number_key_offset)
   {						// Autoincrement at key-start
     error=ha_berkeley::index_last(table->record[1]);
+    /* has taken read lock on page of max key so reserves to infinite  */
+    *nb_reserved_values= ULONGLONG_MAX;
   }
   else
   {
+    /*
+      MySQL needs to call us for next row: assume we are inserting ("a",null)
+      here, we return 3, and next this statement will want to insert ("b",null):
+      there is no reason why ("b",3+1) would be the good row to insert: maybe it
+      already exists, maybe 3+1 is too large...
+    */
+    *nb_reserved_values= 1;
     DBT row,old_key;
     bzero((char*) &row,sizeof(row));
     KEY *key_info= &table->key_info[active_index];
@@ -2191,7 +2291,7 @@
     /* Reading next available number for a sub key */
     ha_berkeley::create_key(&last_key, active_index,
 			    key_buff, table->record[0],
-			    table->s->next_number_key_offset);
+			    table_share->next_number_key_offset);
     /* Store for compare */
     memcpy(old_key.data=key_buff2, key_buff, (old_key.size=last_key.size));
     old_key.app_private=(void*) key_info;
@@ -2221,10 +2321,10 @@
   }
   if (!error)
     nr= (ulonglong)
-      table->next_number_field->val_int_offset(table->s->rec_buff_length)+1;
+      table->next_number_field->val_int_offset(table_share->rec_buff_length)+1;
   ha_berkeley::index_end();
   (void) ha_berkeley::extra(HA_EXTRA_NO_KEYREAD);
-  return nr;
+  *first_value= nr;
 }
 
 void ha_berkeley::print_error(int error, myf errflag)
@@ -2271,48 +2371,14 @@
   berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
   DBUG_ASSERT(trx);
 
-  /*
-   Original bdb documentation says:
-   "The DB->stat method cannot be transaction-protected.
-   For this reason, it should be called in a thread of
-   control that has no open cursors or active transactions."
-   So, let's check if there are any changes have been done since
-   the beginning of the transaction..
-  */
-
-  if (!db_env->txn_stat(db_env, &txn_stat_ptr, 0) &&
-      txn_stat_ptr && txn_stat_ptr->st_nactive>=2)
-  {
-    DB_TXN_ACTIVE *atxn_stmt= 0, *atxn_all= 0;
-
-    u_int32_t all_id= trx->all->id(trx->all);
-    u_int32_t stmt_id= trx->stmt->id(trx->stmt);
-
-    DB_TXN_ACTIVE *cur= txn_stat_ptr->st_txnarray;
-    DB_TXN_ACTIVE *end= cur + txn_stat_ptr->st_nactive;
-    for (; cur!=end && (!atxn_stmt || !atxn_all); cur++)
-    {
-      if (cur->txnid==all_id) atxn_all= cur;
-      if (cur->txnid==stmt_id) atxn_stmt= cur;
-    }
-
-    if (atxn_stmt && atxn_all &&
-	log_compare(&atxn_stmt->lsn,&atxn_all->lsn))
-    {
-      free(txn_stat_ptr);
-      return HA_ADMIN_REJECT;
-    }
-    free(txn_stat_ptr);
-  }
-
-  for (i=0 ; i < table->s->keys ; i++)
+  for (i=0 ; i < table_share->keys ; i++)
   {
     if (stat)
     {
       free(stat);
       stat=0;
     }
-    if ((key_file[i]->stat)(key_file[i], (void*) &stat, 0))
+    if ((key_file[i]->stat)(key_file[i], trx->all, (void*) &stat, 0))
       goto err; /* purecov: inspected */
     share->rec_per_key[i]= (stat->bt_ndata /
 			    (stat->bt_nkeys ? stat->bt_nkeys : 1));
@@ -2325,7 +2391,7 @@
       free(stat);
       stat=0;
     }
-    if ((file->stat)(file, (void*) &stat, 0))
+    if ((file->stat)(file, trx->all, (void*) &stat, 0))
       goto err; /* purecov: inspected */
   }
   pthread_mutex_lock(&share->mutex);
@@ -2380,7 +2446,8 @@
 			   (hidden_primary_key ? berkeley_cmp_hidden_key :
 			    berkeley_cmp_packed_key));
   tmp_file->app_private= (void*) (table->key_info+table->primary_key);
-  fn_format(name_buff,share->table_name,"", ha_berkeley_ext, 2 | 4);
+  fn_format(name_buff,share->table_name.str,"", ha_berkeley_ext,
+            MY_UNPACK_FILENAME|MY_APPEND_EXT);      
   if ((error=tmp_file->verify(tmp_file, name_buff, NullS, (FILE*) 0,
 			      hidden_primary_key ? 0 : DB_NOORDERCHK)))
   {
@@ -2454,7 +2521,7 @@
       share->rec_per_key = rec_per_key;
       share->table_name = tmp_name;
       share->table_name_length=length;
-      strmov(share->table_name,table_name);
+      strmov(share->table_name, table_name);
       share->key_file = key_file;
       share->key_type = key_type;
       if (my_hash_insert(&bdb_open_tables, (byte*) share))
@@ -2515,7 +2582,7 @@
     if (!(share->status & STATUS_PRIMARY_KEY_INIT))
     {
       (void) extra(HA_EXTRA_KEYREAD);
-      index_init(primary_key);
+      index_init(primary_key, 0);
       if (!index_last(table->record[1]))
 	share->auto_ident=uint5korr(current_ident);
       index_end();
@@ -2526,7 +2593,8 @@
       char name_buff[FN_REFLEN];
       uint open_mode= (((table->db_stat & HA_READ_ONLY) ? DB_RDONLY : 0)
 		       | DB_THREAD);
-      fn_format(name_buff, share->table_name,"", ha_berkeley_ext, 2 | 4);
+      fn_format(name_buff, share->table_name, "", ha_berkeley_ext,
+                MY_UNPACK_FILENAME|MY_APPEND_EXT);
       if (!db_create(&share->status_block, db_env, 0))
       {
 	if (share->status_block->open(share->status_block, NULL, name_buff,
@@ -2540,7 +2608,7 @@
     if (!(share->status & STATUS_ROW_COUNT_INIT) && share->status_block)
     {
       share->org_rows= share->rows=
-	table->s->max_rows ? table->s->max_rows : HA_BERKELEY_MAX_ROWS;
+	table_share->max_rows ? table_share->max_rows : HA_BERKELEY_MAX_ROWS;
       if (!share->status_block->cursor(share->status_block, 0, &cursor, 0))
       {
 	DBT row;
@@ -2555,7 +2623,7 @@
 	  uint i;
 	  uchar *pos=(uchar*) row.data;
 	  share->org_rows=share->rows=uint4korr(pos); pos+=4;
-	  for (i=0 ; i < table->s->keys ; i++)
+	  for (i=0 ; i < table_share->keys ; i++)
 	  {
 	    share->rec_per_key[i]=uint4korr(pos);
             pos+=4;
@@ -2607,8 +2675,9 @@
 	goto end; /* purecov: inspected */
       share->status_block->set_flags(share->status_block,0); /* purecov: inspected */
       if (share->status_block->open(share->status_block, NULL,
-				    fn_format(name_buff,share->table_name,"",
-					      ha_berkeley_ext,2 | 4),
+				    fn_format(name_buff,share->table_name,
+                                              "", ha_berkeley_ext,
+                                              MY_UNPACK_FILENAME|MY_APPEND_EXT),
 				    "status", DB_BTREE,
 				    DB_THREAD | DB_CREATE, my_umask)) /* purecov: inspected */
 	goto end; /* purecov: inspected */
@@ -2620,7 +2689,7 @@
       {
 	int4store(pos,share->rec_per_key[i]); pos+=4;
       }
-      DBUG_PRINT("info",("updating status for %s",share->table_name));
+      DBUG_PRINT("info",("updating status for %s", share->table_name));
       (void) write_status(share->status_block, rec_buff,
 			  (uint) (pos-rec_buff));
       share->status&= ~STATUS_BDB_ANALYZE;
@@ -2650,7 +2719,7 @@
 
   int result;
   Field *field;
-  KEY *key_info=table->key_info+table->s->primary_key;
+  KEY *key_info=table->key_info+table_share->primary_key;
   KEY_PART_INFO *key_part=key_info->key_part;
   KEY_PART_INFO *end=key_part+key_info->key_parts;
 
@@ -2668,4 +2737,30 @@
   return 0;
 }
 
-#endif /* HAVE_BERKELEY_DB */
+
+bool ha_berkeley::check_if_incompatible_data(HA_CREATE_INFO *info,
+					     uint table_changes)
+{
+  if (table_changes < IS_EQUAL_YES)
+    return COMPATIBLE_DATA_NO;
+  return COMPATIBLE_DATA_YES;
+}
+
+struct st_mysql_storage_engine berkeley_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION, &berkeley_hton };
+
+mysql_declare_plugin(berkeley)
+{
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &berkeley_storage_engine,
+  berkeley_hton_name,
+  "Sleepycat Software",
+  "Supports transactions and page-level locking",
+  berkeley_init, /* Plugin Init */
+  NULL, /* Plugin Deinit */
+  0x0100, /* 1.0 */
+  0
+}
+mysql_declare_plugin_end;
+
+#endif

--- 1.70.6.1/sql/ha_berkeley.h	2007-02-22 16:59:55 +02:00
+++ 1.88/BitKeeper/deleted/.del-ha_berkeley.h	2007-02-22 17:48:11 +02:00
@@ -83,21 +83,20 @@
   DBT *get_pos(DBT *to, byte *pos);
 
  public:
-  ha_berkeley(TABLE *table_arg);
+  ha_berkeley(TABLE_SHARE *table_arg);
   ~ha_berkeley() {}
   const char *table_type() const { return "BerkeleyDB"; }
   ulong index_flags(uint idx, uint part, bool all_parts) const;
   const char *index_type(uint key_number) { return "BTREE"; }
   const char **bas_ext() const;
-  ulong table_flags(void) const { return int_table_flags; }
+  ulonglong table_flags(void) const { return int_table_flags; }
   uint max_supported_keys()        const { return MAX_KEY-1; }
-  uint extra_rec_buf_length()	 { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; }
+  uint extra_rec_buf_length() const { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; }
   ha_rows estimate_rows_upper_bound();
   uint max_supported_key_length() const { return UINT_MAX32; }
   uint max_supported_key_part_length() const { return UINT_MAX32; }
 
   const key_map *keys_to_use_for_scanning() { return &key_map_full; }
-  bool has_transactions()  { return 1;}
 
   int open(const char *name, int mode, uint test_if_locked);
   int close(void);
@@ -105,7 +104,7 @@
   int write_row(byte * buf);
   int update_row(const byte * old_data, byte * new_data);
   int delete_row(const byte * buf);
-  int index_init(uint index);
+  int index_init(uint index, bool sorted);
   int index_end();
   int index_read(byte * buf, const byte * key,
 		 uint key_len, enum ha_rkey_function find_flag);
@@ -142,22 +141,33 @@
 
   void get_status();
   void get_auto_primary_key(byte *to);
-  ulonglong get_auto_increment();
+  virtual void get_auto_increment(ulonglong offset, ulonglong increment,
+                                  ulonglong nb_desired_values,
+                                  ulonglong *first_value,
+                                  ulonglong *nb_reserved_values);
   void print_error(int error, myf errflag);
   uint8 table_cache_type() { return HA_CACHE_TBL_TRANSACT; }
   bool primary_key_is_clustered() { return true; }
   int cmp_ref(const byte *ref1, const byte *ref2);
+  bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
 };
 
+extern const u_int32_t bdb_DB_TXN_NOSYNC;
+extern const u_int32_t bdb_DB_RECOVER;
+extern const u_int32_t bdb_DB_PRIVATE;
+extern const u_int32_t bdb_DB_DIRECT_DB;
+extern const u_int32_t bdb_DB_DIRECT_LOG;
 extern bool berkeley_shared_data;
 extern u_int32_t berkeley_init_flags,berkeley_env_flags, berkeley_lock_type,
                  berkeley_lock_types[];
-extern ulong berkeley_cache_size, berkeley_max_lock, berkeley_log_buffer_size;
+extern ulong berkeley_max_lock, berkeley_log_buffer_size;
+extern ulonglong berkeley_cache_size;
+extern ulong berkeley_region_size, berkeley_cache_parts;
 extern char *berkeley_home, *berkeley_tmpdir, *berkeley_logdir;
 extern long berkeley_lock_scan_time;
 extern TYPELIB berkeley_lock_typelib;
 
-bool berkeley_init(void);
-bool berkeley_end(void);
+int berkeley_init(void);
+int berkeley_end(ha_panic_function type);
 bool berkeley_flush_logs(void);
-int berkeley_show_logs(Protocol *protocol);
+bool berkeley_show_status(THD *thd, stat_print_fn *print, enum ha_stat_type);

--- 1.243/sql/item.cc	2007-02-22 11:42:34 +02:00
+++ 1.244/sql/item.cc	2007-02-22 17:48:12 +02:00
@@ -1553,6 +1553,8 @@
       doesn't display each argument's characteristics.
     - if nargs is 1, then this error cannot happen.
   */
+  LINT_INIT(safe_args[0]);
+  LINT_INIT(safe_args[1]);
   if (nargs >=2 && nargs <= 3)
   {
     safe_args[0]= args[0];

--- 1.158/sql/item_timefunc.cc	2007-02-22 10:53:27 +02:00
+++ 1.159/sql/item_timefunc.cc	2007-02-22 17:48:12 +02:00
@@ -1587,7 +1587,7 @@
 void Item_func_sysdate_local::store_now_in_TIME(TIME *now_time)
 {
   THD *thd= current_thd;
-  thd->variables.time_zone->gmt_sec_to_TIME(now_time, time(NULL));
+  thd->variables.time_zone->gmt_sec_to_TIME(now_time, (my_time_t) time(NULL));
   thd->time_zone_used= 1;
 }
 

--- 1.620/sql/mysqld.cc	2007-02-22 11:42:34 +02:00
+++ 1.621/sql/mysqld.cc	2007-02-22 17:56:57 +02:00
@@ -3418,7 +3418,7 @@
 #ifdef HAVE_REPLICATION
   if (opt_bin_log && expire_logs_days)
   {
-    long purge_time= time(0) - expire_logs_days*24*60*60;
+    long purge_time= (long) (time(0) - expire_logs_days*24*60*60);
     if (purge_time >= 0)
       mysql_bin_log.purge_logs_before_date(purge_time);
   }

--- 1.228/sql/sql_acl.cc	2007-01-17 20:45:40 +02:00
+++ 1.229/sql/sql_acl.cc	2007-02-22 17:48:12 +02:00
@@ -5169,6 +5169,8 @@
       user= grant_name->user;
       host= grant_name->host.hostname;
       break;
+    default:
+      assert(0);
     }
     if (! user)
       user= "";

--- 1.375/sql/sql_base.cc	2007-02-22 10:50:30 +02:00
+++ 1.376/sql/sql_base.cc	2007-02-22 17:48:12 +02:00
@@ -3813,6 +3813,7 @@
   if (nj_col->view_field)
   {
     Item *item;
+    LINT_INIT(arena);
     if (register_tree_change)
       arena= thd->activate_stmt_arena_if_needed(&backup);
     /*

--- 1.248/sql/sql_insert.cc	2007-02-22 11:40:12 +02:00
+++ 1.249/sql/sql_insert.cc	2007-02-22 17:48:12 +02:00
@@ -396,6 +396,7 @@
 #ifndef EMBEDDED_LIBRARY
   if (lock_type == TL_WRITE_DELAYED)
   {
+    res= 1;
     if (thd->locked_tables)
     {
       DBUG_ASSERT(table_list->db); /* Must be set in the parser */

--- 1.493/sql/sql_select.cc	2007-02-22 11:42:34 +02:00
+++ 1.494/sql/sql_select.cc	2007-02-22 17:48:13 +02:00
@@ -8264,7 +8264,7 @@
       */
       if (nested_join->join_list.elements != 1)
       {
-        nested_join->nj_map= 1 << first_unused++;
+        nested_join->nj_map= (nested_join_map) 1 << first_unused++;
         first_unused= build_bitmap_for_nested_joins(&nested_join->join_list,
                                                     first_unused);
       }
@@ -10332,7 +10332,6 @@
   else
   {
     DBUG_ASSERT(join->tables);
-    DBUG_ASSERT(join_tab);
     error= sub_select(join,join_tab,0);
     if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
       error= sub_select(join,join_tab,1);

--- 1.393/sql/sql_show.cc	2007-02-22 10:53:28 +02:00
+++ 1.394/sql/sql_show.cc	2007-02-22 17:56:57 +02:00
@@ -2938,20 +2938,21 @@
     if (file->stats.create_time)
     {
       thd->variables.time_zone->gmt_sec_to_TIME(&time,
-                                                file->stats.create_time);
+                                                (my_time_t) file->stats.create_time);
       table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
       table->field[14]->set_notnull();
     }
     if (file->stats.update_time)
     {
       thd->variables.time_zone->gmt_sec_to_TIME(&time,
-                                                file->stats.update_time);
+                                                (my_time_t) file->stats.update_time);
       table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
       table->field[15]->set_notnull();
     }
     if (file->stats.check_time)
     {
-      thd->variables.time_zone->gmt_sec_to_TIME(&time, file->stats.check_time);
+      thd->variables.time_zone->gmt_sec_to_TIME(&time,
+                                                (my_time_t) file->stats.check_time);
       table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
       table->field[16]->set_notnull();
     }

--- 1.97/sql/unireg.cc	2007-02-22 10:53:29 +02:00
+++ 1.98/sql/unireg.cc	2007-02-22 17:56:58 +02:00
@@ -913,7 +913,10 @@
                                 field->interval, 
                                 field->field_name);
     if (!regfield)
+    {
+      error= 1;
       goto err;                                 // End of memory
+    }
 
     /* save_in_field() will access regfield->table->in_use */
     regfield->init(&table);

--- 1.65/strings/ctype-ucs2.c	2006-12-23 21:20:33 +02:00
+++ 1.66/strings/ctype-ucs2.c	2007-02-22 17:48:13 +02:00
@@ -206,6 +206,7 @@
   const uchar *se=s+slen;
   const uchar *te=t+tlen;
   MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+  LINT_INIT(s_wc);
 
   while ( s < se && t < te )
   {
@@ -320,7 +321,8 @@
   const char *se=s+len;
   const char *te=t+len;
   MY_UNICASE_INFO **uni_plane= cs->caseinfo;
-  
+  LINT_INIT(s_wc);
+
   while ( s < se && t < te )
   {
     int plane;
@@ -1382,6 +1384,7 @@
   my_wc_t s_wc,t_wc;
   const uchar *se=s+slen;
   const uchar *te=t+tlen;
+  LINT_INIT(s_wc);
 
   while ( s < se && t < te )
   {

--- 1.109/strings/ctype-utf8.c	2007-01-24 19:57:04 +02:00
+++ 1.110/strings/ctype-utf8.c	2007-02-22 17:48:13 +02:00
@@ -2312,6 +2312,7 @@
   const uchar *se=s+slen;
   const uchar *te=t+tlen;
   MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+  LINT_INIT(s_wc);
 
   while ( s < se && t < te )
   {
@@ -2381,6 +2382,7 @@
   my_wc_t s_wc,t_wc;
   const uchar *se= s+slen, *te= t+tlen;
   MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+  LINT_INIT(s_wc);
 
 #ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
   diff_if_only_endspace_difference= 0;

--- 1.65/mysys/my_getopt.c	2007-02-22 10:50:29 +02:00
+++ 1.66/mysys/my_getopt.c	2007-02-22 17:48:12 +02:00
@@ -194,6 +194,7 @@
 	  Find first the right option. Return error in case of an ambiguous,
 	  or unknown option
 	*/
+        LINT_INIT(prev_found);
 	optp= longopts;
 	if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
 	{

--- 1.7/support-files/compiler_warnings.supp	2007-02-22 16:35:29 +02:00
+++ 1.8/support-files/compiler_warnings.supp	2007-02-22 17:56:58 +02:00
@@ -12,3 +12,11 @@
 kernel_types.h : .*'struct Local_key' only defines private constructors and has no friends.*
 lgman.hpp : .*'struct Lgman::Buffer_idx' only defines private constructors and has no friends.*
 SchemaFile.hpp : .*'struct SchemaFile::TableEntry' only defines private constructors and has no friends.*
+sql_yacc.cc : .*switch statement contains 'default' but no 'case' labels.*
+
+#
+# Ignore all conversion warnings on windows 64
+# (Is safe as we are not yet supporting strings >= 2G)
+#
+.* : conversion from 'size_t' to .*int'.*
+.* : conversion from '__int64' to .*int'.*

--- 1.25/server-tools/instance-manager/mysqlmanager.cc	2006-12-31 02:06:33 +02:00
+++ 1.26/server-tools/instance-manager/mysqlmanager.cc	2007-02-22 17:56:57 +02:00
@@ -225,7 +225,7 @@
   MY_INIT(progname);
   log_init();
   umask(0117);
-  srand((unsigned int) time(0));
+  srand((uint) time(0));
 }
 
 

--- 1.17.8.1/ndb/include/kernel/signaldata/DictTabInfo.hpp	2007-02-22 16:59:54 +02:00
+++ 1.36/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp	2007-02-22 17:48:13 +02:00
@@ -20,8 +20,8 @@
 #include <AttributeDescriptor.hpp>
 #include <SimpleProperties.hpp>
 #include <ndb_limits.h>
-#include <trigger_definitions.h>
 #include <NdbSqlUtil.hpp>
+#include <ndb_global.h>
 
 #ifndef my_decimal_h
 
@@ -89,9 +89,9 @@
     CopyTable           = 3, // Between DICT's
     ReadTableFromDiskSR = 4, // Local in DICT
     GetTabInfoConf      = 5,
-    AlterTableFromAPI  = 6
+    AlterTableFromAPI   = 6
   };
-
+  
   enum KeyValues {
     TableName          = 1,  // String, Mandatory
     TableId            = 2,  //Mandatory between DICT's otherwise not allowed
@@ -117,15 +117,29 @@
     FrmLen             = 26,
     FrmData            = 27,
 
+    TableTemporaryFlag = 28,  //Default not Temporary
+
     FragmentCount      = 128, // No of fragments in table (!fragment replicas)
     FragmentDataLen    = 129,
     FragmentData       = 130, // CREATE_FRAGMENTATION reply
-
+    TablespaceId       = 131,
+    TablespaceVersion  = 132,
+    TablespaceDataLen  = 133,
+    TablespaceData     = 134,
+    RangeListDataLen   = 135,
+    RangeListData      = 136,
+    ReplicaDataLen     = 137,
+    ReplicaData        = 138,
     MaxRowsLow         = 139,
     MaxRowsHigh        = 140,
+    DefaultNoPartFlag  = 141,
+    LinearHashFlag     = 142,
     MinRowsLow         = 143,
     MinRowsHigh        = 144,
 
+    RowGCIFlag         = 150,
+    RowChecksumFlag    = 151,
+    
     TableEnd           = 999,
     
     AttributeName          = 1000, // String, Mandatory
@@ -134,7 +148,7 @@
     AttributeSize          = 1003, //Default DictTabInfo::a32Bit
     AttributeArraySize     = 1005, //Default 1
     AttributeKeyFlag       = 1006, //Default noKey
-    AttributeStorage       = 1007, //Default MainMemory
+    AttributeStorageType   = 1007, //Default NDB_STORAGETYPE_MEMORY
     AttributeNullableFlag  = 1008, //Default NotNullable
     AttributeDKey          = 1010, //Default NotDKey
     AttributeExtType       = 1013, //Default ExtUnsigned
@@ -142,7 +156,8 @@
     AttributeExtScale      = 1015, //Default 0
     AttributeExtLength     = 1016, //Default 0
     AttributeAutoIncrement = 1017, //Default false
-    AttributeDefaultValue  = 1018, //Default value (printable string)
+    AttributeDefaultValue  = 1018, //Default value (printable string),
+    AttributeArrayType     = 1019, //Default NDB_ARRAYTYPE_FIXED
     AttributeEnd           = 1999  //
   };
   // ----------------------------------------------------------------------
@@ -157,7 +172,12 @@
     AllNodesSmallTable = 0,
     AllNodesMediumTable = 1,
     AllNodesLargeTable = 2,
-    SingleFragment = 3
+    SingleFragment = 3,
+    DistrKeyHash = 4,
+    DistrKeyLin = 5,
+    UserDefined = 6,
+    DistrKeyUniqueHashIndex = 7,
+    DistrKeyOrderedIndex = 8
   };
   
   // TableType constants + objects
@@ -170,11 +190,21 @@
     UniqueOrderedIndex = 5,
     OrderedIndex = 6,
     // constant 10 hardcoded in Dbdict.cpp
-    HashIndexTrigger = 10 + TriggerType::SECONDARY_INDEX,
-    SubscriptionTrigger = 10 + TriggerType::SUBSCRIPTION,
-    ReadOnlyConstraint = 10 + TriggerType::READ_ONLY_CONSTRAINT,
-    IndexTrigger = 10 + TriggerType::ORDERED_INDEX
+    HashIndexTrigger = 11,
+    SubscriptionTrigger = 16,
+    ReadOnlyConstraint = 17,
+    IndexTrigger = 18,
+    
+    Tablespace = 20,        ///< Tablespace
+    LogfileGroup = 21,      ///< Logfile group
+    Datafile = 22,          ///< Datafile
+    Undofile = 23           ///< Undofile
   };
+
+  // used 1) until type BlobTable added 2) in upgrade code
+  static bool
+  isBlobTableName(const char* name, Uint32* ptab_id = 0, Uint32* pcol_no = 0);
+  
   static inline bool
   isTable(int tableType) {
     return
@@ -213,7 +243,28 @@
       tableType == UniqueOrderedIndex ||
       tableType == OrderedIndex;
   }
+  static inline bool
+  isTrigger(int tableType) {
+    return
+      tableType == HashIndexTrigger ||
+      tableType == SubscriptionTrigger ||
+      tableType == ReadOnlyConstraint ||
+      tableType == IndexTrigger;
+  }
+  static inline bool
+  isFilegroup(int tableType) {
+    return
+      tableType == Tablespace ||
+      tableType == LogfileGroup;
+  }
 
+  static inline bool
+  isFile(int tableType) {
+    return
+      tableType == Datafile||
+      tableType == Undofile;
+  }
+  
   // Object state for translating from/to API
   enum ObjectState {
     StateUndefined = 0,
@@ -228,7 +279,7 @@
   // Object store for translating from/to API
   enum ObjectStore {
     StoreUndefined = 0,
-    StoreTemporary = 1,
+    StoreNotLogged = 1,
     StorePermanent = 2
   };
   
@@ -247,6 +298,7 @@
     char   PrimaryTable[MAX_TAB_NAME_SIZE]; // Only used when "index"
     Uint32 PrimaryTableId;
     Uint32 TableLoggedFlag;
+    Uint32 TableTemporaryFlag;
     Uint32 NoOfKeyAttr;
     Uint32 NoOfAttributes;
     Uint32 NoOfNullable;
@@ -256,7 +308,6 @@
     Uint32 MaxLoadFactor;
     Uint32 KeyLength;
     Uint32 FragmentType;
-    Uint32 TableStorage;
     Uint32 TableType;
     Uint32 TableVersion;
     Uint32 IndexState;
@@ -264,15 +315,35 @@
     Uint32 UpdateTriggerId;
     Uint32 DeleteTriggerId;
     Uint32 CustomTriggerId;
+    Uint32 TablespaceId;
+    Uint32 TablespaceVersion;
+    Uint32 DefaultNoPartFlag;
+    Uint32 LinearHashFlag;
+    /*
+      TODO RONM:
+      We need to replace FRM, Fragment Data, Tablespace Data and in
+      very particular RangeListData with dynamic arrays
+    */
     Uint32 FrmLen;
     char   FrmData[MAX_FRM_DATA_SIZE];
     Uint32 FragmentCount;
+    Uint32 ReplicaDataLen;
+    Uint16 ReplicaData[MAX_FRAGMENT_DATA_BYTES];
     Uint32 FragmentDataLen;
-    Uint16 FragmentData[(MAX_FRAGMENT_DATA_BYTES+1)/2];
+    Uint16 FragmentData[3*MAX_NDB_PARTITIONS];
+
     Uint32 MaxRowsLow;
     Uint32 MaxRowsHigh;
     Uint32 MinRowsLow;
     Uint32 MinRowsHigh;
+
+    Uint32 TablespaceDataLen;
+    Uint32 TablespaceData[2*MAX_NDB_PARTITIONS];
+    Uint32 RangeListDataLen;
+    char   RangeListData[4*2*MAX_NDB_PARTITIONS*2];
+    
+    Uint32 RowGCIFlag;
+    Uint32 RowChecksumFlag;
     
     Table() {}
     void init();
@@ -325,6 +396,7 @@
     Uint32 AttributeType; // for osu 4.1->5.0.x
     Uint32 AttributeSize;
     Uint32 AttributeArraySize;
+    Uint32 AttributeArrayType;
     Uint32 AttributeKeyFlag;
     Uint32 AttributeNullableFlag;
     Uint32 AttributeDKey;
@@ -333,6 +405,7 @@
     Uint32 AttributeExtScale;
     Uint32 AttributeExtLength;
     Uint32 AttributeAutoIncrement;
+    Uint32 AttributeStorageType;
     char   AttributeDefaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
     
     Attribute() {}
@@ -470,8 +543,9 @@
       fprintf(out, "AttributeType = %d\n", AttributeType);
       fprintf(out, "AttributeSize = %d\n", AttributeSize);
       fprintf(out, "AttributeArraySize = %d\n", AttributeArraySize);
+      fprintf(out, "AttributeArrayType = %d\n", AttributeArrayType);
       fprintf(out, "AttributeKeyFlag = %d\n", AttributeKeyFlag);
-      fprintf(out, "AttributeStorage = %d\n", AttributeStorage);
+      fprintf(out, "AttributeStorageType = %d\n", AttributeStorageType);
       fprintf(out, "AttributeNullableFlag = %d\n", AttributeNullableFlag);
       fprintf(out, "AttributeDKey = %d\n", AttributeDKey);
       fprintf(out, "AttributeGroup = %d\n", AttributeGroup);
@@ -509,20 +583,142 @@
   Uint32 tabInfoData[DataLength];
 
 public:
-  enum Depricated 
+  enum Depricated
   {
     AttributeDGroup    = 1009, //Default NotDGroup
     AttributeStoredInd = 1011, //Default NotStored
+    TableStorageVal    = 14, //Disk storage specified per attribute
     SecondTableId      = 17, //Mandatory between DICT's otherwise not allowed
     FragmentKeyTypeVal = 16 //Default PrimaryKey
   };
-  
-  enum Unimplemented 
+    
+  enum Unimplemented
   {
-    TableStorageVal    = 14, //Default StorageType::MainMemory
     ScanOptimised      = 15, //Default updateOptimised
-    AttributeGroup     = 1012 //Default 0
+    AttributeGroup     = 1012, //Default 0
+    FileNo             = 102
+  };
+};
+
+#define DFGIMAP(x, y, z) \
+  { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::Uint32Value, 0, (~0), 0 }
+
+#define DFGIMAP2(x, y, z, u, v) \
+  { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::Uint32Value, u, v, 0 }
+
+#define DFGIMAPS(x, y, z, u, v) \
+  { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::StringValue, u, v, 0 }
+
+#define DFGIMAPB(x, y, z, u, v, l) \
+  { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::BinaryValue, u, v, \
+                     my_offsetof(x, l) }
+
+#define DFGIBREAK(x) \
+  { DictFilegroupInfo::x, 0, SimpleProperties::InvalidValue, 0, 0, 0 }
+
+struct DictFilegroupInfo {
+  enum KeyValues {
+    FilegroupName     = 1,
+    FilegroupType     = 2,
+    FilegroupId       = 3,
+    FilegroupVersion  = 4,
+
+    /**
+     * File parameters
+     */
+    FileName          = 100,
+    FileType          = 101,
+    FileId            = 103,
+    FileFGroupId      = 104,
+    FileFGroupVersion = 105,
+    FileSizeHi        = 106,
+    FileSizeLo        = 107,
+    FileFreeExtents   = 108,
+    FileVersion       = 109,
+    FileEnd           = 199, //    
+
+    /**
+     * Tablespace parameters
+     */
+    TS_ExtentSize          = 1000, // specified in bytes
+    TS_LogfileGroupId      = 1001, 
+    TS_LogfileGroupVersion = 1002, 
+    TS_GrowLimit           = 1003, // In bytes
+    TS_GrowSizeHi          = 1004,
+    TS_GrowSizeLo          = 1005,
+    TS_GrowPattern         = 1006,
+    TS_GrowMaxSize         = 1007,
+
+    /**
+     * Logfile group parameters
+     */
+    LF_UndoBufferSize  = 2005, // In bytes
+    LF_UndoGrowLimit   = 2000, // In bytes
+    LF_UndoGrowSizeHi  = 2001,
+    LF_UndoGrowSizeLo  = 2002,
+    LF_UndoGrowPattern = 2003,
+    LF_UndoGrowMaxSize = 2004,
+    LF_UndoFreeWordsHi = 2006,
+    LF_UndoFreeWordsLo = 2007
+  };
+
+  // FragmentType constants
+  enum FileTypeValues {
+    Datafile = 0,
+    Undofile = 1
+    //, Redofile
+  };
+ 
+  struct GrowSpec {
+    Uint32 GrowLimit;
+    Uint32 GrowSizeHi;
+    Uint32 GrowSizeLo;
+    char   GrowPattern[PATH_MAX];
+    Uint32 GrowMaxSize;
+  };
+  
+  // Table data interpretation
+  struct Filegroup {
+    char   FilegroupName[MAX_TAB_NAME_SIZE];
+    Uint32 FilegroupType; // ObjType
+    Uint32 FilegroupId;
+    Uint32 FilegroupVersion;
+
+    union {
+      Uint32 TS_ExtentSize;
+      Uint32 LF_UndoBufferSize;
+    };
+    Uint32 TS_LogfileGroupId;
+    Uint32 TS_LogfileGroupVersion;
+    union {
+      GrowSpec TS_DataGrow;
+      GrowSpec LF_UndoGrow;
+    };
+    //GrowSpec LF_RedoGrow;
+    Uint32 LF_UndoFreeWordsHi;
+    Uint32 LF_UndoFreeWordsLo;
+    Filegroup() {}
+    void init();
+  };
+  static const Uint32 MappingSize;
+  static const SimpleProperties::SP2StructMapping Mapping[];
+
+  struct File {
+    char FileName[PATH_MAX];
+    Uint32 FileType;
+    Uint32 FileId;
+    Uint32 FileVersion;
+    Uint32 FilegroupId;
+    Uint32 FilegroupVersion;
+    Uint32 FileSizeHi;
+    Uint32 FileSizeLo;
+    Uint32 FileFreeExtents;
+
+    File() {}
+    void init();
   };
+  static const Uint32 FileMappingSize;
+  static const SimpleProperties::SP2StructMapping FileMapping[];
 };
 
 #endif

--- 1.17/mysys/base64.c	2006-12-23 21:19:45 +02:00
+++ 1.18/mysys/base64.c	2007-02-22 17:48:11 +02:00
@@ -100,10 +100,10 @@
 }
 
 
-static inline unsigned
+static inline uint
 pos(unsigned char c)
 {
-  return strchr(base64_table, c) - base64_table;
+  return (uint) (strchr(base64_table, c) - base64_table);
 }
 
 

--- 1.45/libmysql/libmysql.def	2006-04-30 23:13:53 +03:00
+++ 1.46/libmysql/libmysql.def	2007-02-22 17:48:11 +02:00
@@ -1,5 +1,4 @@
 LIBRARY		LIBMYSQL
-DESCRIPTION	'MySQL 5.0 Client Library'
 VERSION		6.0
 EXPORTS
 	_dig_vec_lower

--- 1.4.1.1/innobase/include/ut0byte.ic	2007-02-22 16:59:54 +02:00
+++ 1.8/storage/innobase/include/ut0byte.ic	2007-02-22 17:48:13 +02:00
@@ -22,7 +22,7 @@
 	ut_ad(low <= 0xFFFFFFFF);
 
 	res.high = high;
-	res.low  = low;
+	res.low	 = low;
 
 	return(res);
 }
@@ -62,7 +62,7 @@
 	dulint	d)	/* in: dulint */
 {
 	return((ib_longlong)d.low
-		+ (((ib_longlong)d.high) << 32));
+	       + (((ib_longlong)d.high) << 32));
 }
 
 /***********************************************************
@@ -89,7 +89,7 @@
 ut_dulint_cmp(
 /*==========*/
 			/* out: -1 if a < b, 0 if a == b,
-			1 if a > b */ 
+			1 if a > b */
 	dulint	a,	/* in: dulint */
 	dulint	b)	/* in: dulint */
 {
@@ -186,7 +186,7 @@
 	a.low = 0xFFFFFFFFUL - b;
 
 	ut_ad(a.high > 0);
-	
+
 	a.high--;
 
 	return(a);
@@ -218,9 +218,9 @@
 	diff += 1 + a.low;
 
 	ut_ad(diff > a.low);
-	
+
 	return(diff);
-} 
+}
 
 /************************************************************
 Rounds a dulint downward to a multiple of a power of 2. */
@@ -229,8 +229,8 @@
 ut_dulint_align_down(
 /*=================*/
 				/* out: rounded value */
-	dulint   n,        	/* in: number to be rounded */
-	ulint    align_no)  	/* in: align by this number which must be a
+	dulint	 n,		/* in: number to be rounded */
+	ulint	 align_no)	/* in: align by this number which must be a
 				power of 2 */
 {
 	ulint	low, high;
@@ -240,7 +240,7 @@
 
 	low = ut_dulint_get_low(n);
 	high = ut_dulint_get_high(n);
-	
+
 	low = low & ~(align_no - 1);
 
 	return(ut_dulint_create(high, low));
@@ -253,8 +253,8 @@
 ut_dulint_align_up(
 /*===============*/
 				/* out: rounded value */
-	dulint   n,        	/* in: number to be rounded */
-	ulint    align_no)  	/* in: align by this number which must be a
+	dulint	 n,		/* in: number to be rounded */
+	ulint	 align_no)	/* in: align by this number which must be a
 				power of 2 */
 {
 	return(ut_dulint_align_down(ut_dulint_add(n, align_no - 1), align_no));
@@ -269,8 +269,8 @@
 ut_calc_align(
 /*==========*/
 				/* out: rounded value */
-	ulint    n,        	/* in: number to be rounded */
-	ulint    align_no)  	/* in: align by this number */
+	ulint	 n,		/* in: number to be rounded */
+	ulint	 align_no)	/* in: align by this number */
 {
 	ut_ad(align_no > 0);
 	ut_ad(((align_no - 1) & align_no) == 0);
@@ -285,8 +285,8 @@
 ut_align(
 /*=====*/
 				/* out: aligned pointer */
-	void*   ptr,            /* in: pointer */
-	ulint   align_no)      	/* in: align by this number */
+	void*	ptr,		/* in: pointer */
+	ulint	align_no)	/* in: align by this number */
 {
 	ut_ad(align_no > 0);
 	ut_ad(((align_no - 1) & align_no) == 0);
@@ -306,8 +306,8 @@
 ut_calc_align_down(
 /*===============*/
 				/* out: rounded value */
-	ulint    n,              /* in: number to be rounded */
-	ulint    align_no)       /* in: align by this number */
+	ulint	 n,		 /* in: number to be rounded */
+	ulint	 align_no)	 /* in: align by this number */
 {
 	ut_ad(align_no > 0);
 	ut_ad(((align_no - 1) & align_no) == 0);
@@ -323,8 +323,8 @@
 ut_align_down(
 /*==========*/
 				/* out: aligned pointer */
-	void*   ptr,            /* in: pointer */
-	ulint   align_no)      	/* in: align by this number */
+	void*	ptr,		/* in: pointer */
+	ulint	align_no)	/* in: align by this number */
 {
 	ut_ad(align_no > 0);
 	ut_ad(((align_no - 1) & align_no) == 0);
@@ -344,8 +344,8 @@
 /*============*/
 					/* out: distance from
 					aligned pointer */
-	const void*	ptr,            /* in: pointer */
-	ulint		align_no)      	/* in: align by this number */
+	const void*	ptr,		/* in: pointer */
+	ulint		align_no)	/* in: align by this number */
 {
 	ut_ad(align_no > 0);
 	ut_ad(((align_no - 1) & align_no) == 0);
@@ -368,8 +368,9 @@
 	ulint	n)	/* in: nth bit requested */
 {
 	ut_ad(n < 8 * sizeof(ulint));
-	ut_ad(TRUE == 1);
-
+#if TRUE != 1
+# error "TRUE != 1"
+#endif
 	return(1 & (a >> n));
 }
 
@@ -385,8 +386,9 @@
 	ibool	val)	/* in: value for the bit to set */
 {
 	ut_ad(n < 8 * sizeof(ulint));
-	ut_ad(TRUE == 1);
-
+#if TRUE != 1
+# error "TRUE != 1"
+#endif
 	if (val) {
 		return(((ulint) 1 << n) | a);
 	} else {

--- 1.3.1.1/innobase/include/ut0ut.ic	2007-02-22 16:59:54 +02:00
+++ 1.6/storage/innobase/include/ut0ut.ic	2007-02-22 17:48:13 +02:00
@@ -13,8 +13,8 @@
 ut_min(
 /*===*/
 			/* out: minimum */
-	ulint    n1,	/* in: first number */
-	ulint    n2)	/* in: second number */
+	ulint	 n1,	/* in: first number */
+	ulint	 n2)	/* in: second number */
 {
 	return((n1 <= n2) ? n1 : n2);
 }
@@ -26,8 +26,8 @@
 ut_max(
 /*===*/
 			/* out: maximum */
-	ulint    n1,	/* in: first number */
-	ulint    n2)	/* in: second number */
+	ulint	 n1,	/* in: first number */
+	ulint	 n2)	/* in: second number */
 {
 	return((n1 <= n2) ? n2 : n1);
 }
@@ -44,7 +44,7 @@
 	ulint	b1,	/* in: less significant part of first pair */
 	ulint	a2,	/* in: more significant part of second pair */
 	ulint	b2)	/* in: less significant part of second pair */
-{	
+{
 	if (a1 == a2) {
 		*a = a1;
 		*b = ut_min(b1, b2);
@@ -82,7 +82,7 @@
 int
 ut_pair_cmp(
 /*========*/
-			/* out: -1 if a < b, 0 if a == b, 1 if a > b */ 
+			/* out: -1 if a < b, 0 if a == b, 1 if a > b */
 	ulint	a1,	/* in: more significant part of first pair */
 	ulint	a2,	/* in: less significant part of first pair */
 	ulint	b1,	/* in: more significant part of second pair */

--- 1.202.36.1/sql/ha_innodb.cc	2007-02-22 16:59:55 +02:00
+++ 1.321/storage/innobase/handler/ha_innodb.cc	2007-02-22 17:56:58 +02:00
@@ -6,12 +6,12 @@
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA */
 
 /* This file defines the InnoDB handler: the interface between MySQL and InnoDB
 NOTE: You can only use noninlined InnoDB functions in this file, because we
@@ -30,72 +30,75 @@
 #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>
 #include <mysys_err.h>
 #include <my_sys.h>
-
-#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
-
 #include "ha_innodb.h"
 
-pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */
-                prepare_commit_mutex; /* to force correct commit order in
-				      binlog */
+pthread_mutex_t innobase_share_mutex,	/* to protect innobase_open_files */
+		prepare_commit_mutex;	/* to force correct commit order in
+					binlog */
 ulong commit_threads= 0;
 pthread_mutex_t commit_threads_m;
 pthread_cond_t commit_cond;
 pthread_mutex_t commit_cond_m;
 bool innodb_inited= 0;
 
+/*
+  This needs to exist until the query cache callback is removed
+  or learns to pass hton.
+*/
+static handlerton *legacy_innodb_hton;
+
 /*-----------------------------------------------------------------*/
 /* These variables are used to implement (semi-)synchronous MySQL binlog
 replication for InnoDB tables. */
 
-pthread_cond_t  innobase_repl_cond;             /* Posix cond variable;
-                                                this variable is signaled
-                                                when enough binlog has been
-                                                sent to slave, so that a
-                                                waiting trx can return the
-                                                'ok' message to the client
-                                                for a commit */
-pthread_mutex_t innobase_repl_cond_mutex;       /* Posix cond variable mutex
-                                                that also protects the next
-                                                innobase_repl_... variables */
-uint            innobase_repl_state;            /* 1 if synchronous replication
-                                                is switched on and is working
-                                                ok; else 0 */
-uint            innobase_repl_file_name_inited  = 0; /* This is set to 1 when
-                                                innobase_repl_file_name
-                                                contains meaningful data */
-char*           innobase_repl_file_name;        /* The binlog name up to which
-                                                we have sent some binlog to
-                                                the slave */
-my_off_t        innobase_repl_pos;              /* The position in that file
-                                                up to which we have sent the
-                                                binlog to the slave */
-uint            innobase_repl_n_wait_threads    = 0; /* This tells how many
-                                                transactions currently are
-                                                waiting for the binlog to be
-                                                sent to the client */
-uint            innobase_repl_wait_file_name_inited = 0; /* This is set to 1
-                                                when we know the 'smallest'
-                                                wait position */
-char*           innobase_repl_wait_file_name;   /* NULL, or the 'smallest'
-                                                innobase_repl_file_name that
-                                                a transaction is waiting for */
-my_off_t        innobase_repl_wait_pos;         /* The smallest position in
-                                                that file that a trx is
-                                                waiting for: the trx can
-                                                proceed and send an 'ok' to
-                                                the client when MySQL has sent
-                                                the binlog up to this position
-                                                to the slave */
+pthread_cond_t	innobase_repl_cond;		/* Posix cond variable;
+						this variable is signaled
+						when enough binlog has been
+						sent to slave, so that a
+						waiting trx can return the
+						'ok' message to the client
+						for a commit */
+pthread_mutex_t innobase_repl_cond_mutex;	/* Posix cond variable mutex
+						that also protects the next
+						innobase_repl_... variables */
+uint		innobase_repl_state;		/* 1 if synchronous replication
+						is switched on and is working
+						ok; else 0 */
+uint		innobase_repl_file_name_inited	= 0; /* This is set to 1 when
+						innobase_repl_file_name
+						contains meaningful data */
+char*		innobase_repl_file_name;	/* The binlog name up to which
+						we have sent some binlog to
+						the slave */
+my_off_t	innobase_repl_pos;		/* The position in that file
+						up to which we have sent the
+						binlog to the slave */
+uint		innobase_repl_n_wait_threads	= 0; /* This tells how many
+						transactions currently are
+						waiting for the binlog to be
+						sent to the client */
+uint		innobase_repl_wait_file_name_inited = 0; /* This is set to 1
+						when we know the 'smallest'
+						wait position */
+char*		innobase_repl_wait_file_name;	/* NULL, or the 'smallest'
+						innobase_repl_file_name that
+						a transaction is waiting for */
+my_off_t	innobase_repl_wait_pos;		/* The smallest position in
+						that file that a trx is
+						waiting for: the trx can
+						proceed and send an 'ok' to
+						the client when MySQL has sent
+						the binlog up to this position
+						to the slave */
 /*-----------------------------------------------------------------*/
 
 
@@ -110,43 +113,45 @@
 
 /* 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 */
 #define HA_INNOBASE_RANGE_COUNT	  100
 
-ulong 	innobase_large_page_size = 0;
+ulong	innobase_large_page_size = 0;
 
 /* The default values for the following, type long or longlong, start-up
 parameters are declared in mysqld.cc: */
 
 long innobase_mirrored_log_groups, innobase_log_files_in_group,
-     innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb,
-     innobase_additional_mem_pool_size, innobase_file_io_threads,
-     innobase_lock_wait_timeout, innobase_force_recovery,
-     innobase_open_files;
+	innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb,
+	innobase_additional_mem_pool_size, innobase_file_io_threads,
+	innobase_lock_wait_timeout, innobase_force_recovery,
+	innobase_open_files;
 
 longlong innobase_buffer_pool_size, innobase_log_file_size;
 
@@ -154,7 +159,7 @@
 are determined in innobase_init below: */
 
 char*	innobase_data_home_dir			= NULL;
-char*	innobase_data_file_path 		= NULL;
+char*	innobase_data_file_path			= NULL;
 char*	innobase_log_group_home_dir		= NULL;
 char*	innobase_log_arch_dir			= NULL;/* unused */
 /* The following has a misleading name: starting from 4.0.5, this also
@@ -166,12 +171,12 @@
 
 ulong	innobase_fast_shutdown			= 1;
 my_bool innobase_log_archive			= FALSE;/* unused */
-my_bool innobase_use_doublewrite    = TRUE;
-my_bool innobase_use_checksums      = TRUE;
-my_bool innobase_use_large_pages    = FALSE;
+my_bool innobase_use_doublewrite		= TRUE;
+my_bool innobase_use_checksums			= TRUE;
+my_bool innobase_use_large_pages		= FALSE;
 my_bool	innobase_use_native_aio			= FALSE;
 my_bool	innobase_file_per_table			= FALSE;
-my_bool innobase_locks_unsafe_for_binlog        = FALSE;
+my_bool innobase_locks_unsafe_for_binlog	= FALSE;
 my_bool innobase_rollback_on_timeout		= FALSE;
 my_bool innobase_create_status_file		= FALSE;
 
@@ -185,46 +190,37 @@
 #define INNOBASE_WAKE_INTERVAL	32
 ulong	innobase_active_counter	= 0;
 
-static HASH 	innobase_open_tables;
+static HASH	innobase_open_tables;
 
-#ifdef __NETWARE__  	/* some special cleanup for NetWare */
+#ifdef __NETWARE__	/* some special cleanup for NetWare */
 bool nw_panic = FALSE;
 #endif
 
 static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
-			      my_bool not_used __attribute__((unused)));
+	my_bool not_used __attribute__((unused)));
 static INNOBASE_SHARE *get_share(const char *table_name);
 static void free_share(INNOBASE_SHARE *share);
-static int innobase_close_connection(THD* thd);
-static int innobase_commit(THD* thd, bool all);
-static int innobase_rollback(THD* thd, bool all);
-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);
-
-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
-};
+static int innobase_close_connection(handlerton *hton, THD* thd);
+static int innobase_commit(handlerton *hton, THD* thd, bool all);
+static int innobase_rollback(handlerton *hton, THD* thd, bool all);
+static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd, 
+           void *savepoint);
+static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
+static int innobase_release_savepoint(handlerton *hton, THD* thd, 
+           void *savepoint);
+static handler *innobase_create_handler(handlerton *hton,
+                                        TABLE_SHARE *table,
+                                        MEM_ROOT *mem_root);
+
+static const char innobase_hton_name[]= "InnoDB";
+
+static handler *innobase_create_handler(handlerton *hton,
+                                        TABLE_SHARE *table, 
+                                        MEM_ROOT *mem_root)
+{
+  return new (mem_root) ha_innobase(hton, table);
+}
+
 
 /*********************************************************************
 Commits a transaction in an InnoDB database. */
@@ -234,21 +230,21 @@
 /*================*/
 	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},
+  (char*) &export_vars.innodb_buffer_pool_pages_data,	  SHOW_LONG},
   {"buffer_pool_pages_dirty",
-  (char*) &export_vars.innodb_buffer_pool_pages_dirty,    SHOW_LONG},
+  (char*) &export_vars.innodb_buffer_pool_pages_dirty,	  SHOW_LONG},
   {"buffer_pool_pages_flushed",
   (char*) &export_vars.innodb_buffer_pool_pages_flushed,  SHOW_LONG},
   {"buffer_pool_pages_free",
-  (char*) &export_vars.innodb_buffer_pool_pages_free,     SHOW_LONG},
+  (char*) &export_vars.innodb_buffer_pool_pages_free,	  SHOW_LONG},
   {"buffer_pool_pages_latched",
   (char*) &export_vars.innodb_buffer_pool_pages_latched,  SHOW_LONG},
   {"buffer_pool_pages_misc",
-  (char*) &export_vars.innodb_buffer_pool_pages_misc,     SHOW_LONG},
+  (char*) &export_vars.innodb_buffer_pool_pages_misc,	  SHOW_LONG},
   {"buffer_pool_pages_total",
-  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
+  (char*) &export_vars.innodb_buffer_pool_pages_total,	  SHOW_LONG},
   {"buffer_pool_read_ahead_rnd",
   (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
   {"buffer_pool_read_ahead_seq",
@@ -256,72 +252,73 @@
   {"buffer_pool_read_requests",
   (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
   {"buffer_pool_reads",
-  (char*) &export_vars.innodb_buffer_pool_reads,          SHOW_LONG},
+  (char*) &export_vars.innodb_buffer_pool_reads,	  SHOW_LONG},
   {"buffer_pool_wait_free",
-  (char*) &export_vars.innodb_buffer_pool_wait_free,      SHOW_LONG},
+  (char*) &export_vars.innodb_buffer_pool_wait_free,	  SHOW_LONG},
   {"buffer_pool_write_requests",
   (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
   {"data_fsyncs",
-  (char*) &export_vars.innodb_data_fsyncs,                SHOW_LONG},
+  (char*) &export_vars.innodb_data_fsyncs,		  SHOW_LONG},
   {"data_pending_fsyncs",
-  (char*) &export_vars.innodb_data_pending_fsyncs,        SHOW_LONG},
+  (char*) &export_vars.innodb_data_pending_fsyncs,	  SHOW_LONG},
   {"data_pending_reads",
-  (char*) &export_vars.innodb_data_pending_reads,         SHOW_LONG},
+  (char*) &export_vars.innodb_data_pending_reads,	  SHOW_LONG},
   {"data_pending_writes",
-  (char*) &export_vars.innodb_data_pending_writes,        SHOW_LONG},
+  (char*) &export_vars.innodb_data_pending_writes,	  SHOW_LONG},
   {"data_read",
-  (char*) &export_vars.innodb_data_read,                  SHOW_LONG},
+  (char*) &export_vars.innodb_data_read,		  SHOW_LONG},
   {"data_reads",
-  (char*) &export_vars.innodb_data_reads,                 SHOW_LONG},
+  (char*) &export_vars.innodb_data_reads,		  SHOW_LONG},
   {"data_writes",
-  (char*) &export_vars.innodb_data_writes,                SHOW_LONG},
+  (char*) &export_vars.innodb_data_writes,		  SHOW_LONG},
   {"data_written",
-  (char*) &export_vars.innodb_data_written,               SHOW_LONG},
+  (char*) &export_vars.innodb_data_written,		  SHOW_LONG},
   {"dblwr_pages_written",
-  (char*) &export_vars.innodb_dblwr_pages_written,        SHOW_LONG},
+  (char*) &export_vars.innodb_dblwr_pages_written,	  SHOW_LONG},
   {"dblwr_writes",
-  (char*) &export_vars.innodb_dblwr_writes,               SHOW_LONG},
+  (char*) &export_vars.innodb_dblwr_writes,		  SHOW_LONG},
   {"log_waits",
-  (char*) &export_vars.innodb_log_waits,                  SHOW_LONG},
+  (char*) &export_vars.innodb_log_waits,		  SHOW_LONG},
   {"log_write_requests",
-  (char*) &export_vars.innodb_log_write_requests,         SHOW_LONG},
+  (char*) &export_vars.innodb_log_write_requests,	  SHOW_LONG},
   {"log_writes",
-  (char*) &export_vars.innodb_log_writes,                 SHOW_LONG},
+  (char*) &export_vars.innodb_log_writes,		  SHOW_LONG},
   {"os_log_fsyncs",
-  (char*) &export_vars.innodb_os_log_fsyncs,              SHOW_LONG},
+  (char*) &export_vars.innodb_os_log_fsyncs,		  SHOW_LONG},
   {"os_log_pending_fsyncs",
-  (char*) &export_vars.innodb_os_log_pending_fsyncs,      SHOW_LONG},
+  (char*) &export_vars.innodb_os_log_pending_fsyncs,	  SHOW_LONG},
   {"os_log_pending_writes",
-  (char*) &export_vars.innodb_os_log_pending_writes,      SHOW_LONG},
+  (char*) &export_vars.innodb_os_log_pending_writes,	  SHOW_LONG},
   {"os_log_written",
-  (char*) &export_vars.innodb_os_log_written,             SHOW_LONG},
+  (char*) &export_vars.innodb_os_log_written,		  SHOW_LONG},
   {"page_size",
-  (char*) &export_vars.innodb_page_size,                  SHOW_LONG},
+  (char*) &export_vars.innodb_page_size,		  SHOW_LONG},
   {"pages_created",
-  (char*) &export_vars.innodb_pages_created,              SHOW_LONG},
+  (char*) &export_vars.innodb_pages_created,		  SHOW_LONG},
   {"pages_read",
-  (char*) &export_vars.innodb_pages_read,                 SHOW_LONG},
+  (char*) &export_vars.innodb_pages_read,		  SHOW_LONG},
   {"pages_written",
-  (char*) &export_vars.innodb_pages_written,              SHOW_LONG},
+  (char*) &export_vars.innodb_pages_written,		  SHOW_LONG},
   {"row_lock_current_waits",
-  (char*) &export_vars.innodb_row_lock_current_waits,     SHOW_LONG},
+  (char*) &export_vars.innodb_row_lock_current_waits,	  SHOW_LONG},
   {"row_lock_time",
-  (char*) &export_vars.innodb_row_lock_time,              SHOW_LONGLONG},
+  (char*) &export_vars.innodb_row_lock_time,		  SHOW_LONGLONG},
   {"row_lock_time_avg",
-  (char*) &export_vars.innodb_row_lock_time_avg,          SHOW_LONG},
+  (char*) &export_vars.innodb_row_lock_time_avg,	  SHOW_LONG},
   {"row_lock_time_max",
-  (char*) &export_vars.innodb_row_lock_time_max,          SHOW_LONG},
+  (char*) &export_vars.innodb_row_lock_time_max,	  SHOW_LONG},
   {"row_lock_waits",
-  (char*) &export_vars.innodb_row_lock_waits,             SHOW_LONG},
+  (char*) &export_vars.innodb_row_lock_waits,		  SHOW_LONG},
   {"rows_deleted",
-  (char*) &export_vars.innodb_rows_deleted,               SHOW_LONG},
+  (char*) &export_vars.innodb_rows_deleted,		  SHOW_LONG},
   {"rows_inserted",
-  (char*) &export_vars.innodb_rows_inserted,              SHOW_LONG},
+  (char*) &export_vars.innodb_rows_inserted,		  SHOW_LONG},
   {"rows_read",
-  (char*) &export_vars.innodb_rows_read,                  SHOW_LONG},
+  (char*) &export_vars.innodb_rows_read,		  SHOW_LONG},
   {"rows_updated",
-  (char*) &export_vars.innodb_rows_updated,               SHOW_LONG},
-  {NullS, NullS, SHOW_LONG}};
+  (char*) &export_vars.innodb_rows_updated,		  SHOW_LONG},
+  {NullS, NullS, SHOW_LONG}
+};
 
 /* General functions */
 
@@ -386,23 +383,25 @@
 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)
+         handlerton *hton,
+	 THD *thd)
 {
 	trx_t*	trx;
 
 	if (!innodb_inited) {
 
-		return;
+		return 0;
 	}
 
-	trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*) thd->ha_data[hton->slot];
 
 	if (trx) {
-        	innobase_release_stat_resources(trx);
+		innobase_release_stat_resources(trx);
 	}
+	return 0;
 }
 
 /************************************************************************
@@ -438,30 +437,34 @@
 
 		return(0);
 
-  	} else if (error == (int) DB_DUPLICATE_KEY) {
+	} else if (error == (int) DB_DUPLICATE_KEY) {
 
-    		return(HA_ERR_FOUND_DUPP_KEY);
+		return(HA_ERR_FOUND_DUPP_KEY);
 
- 	} else if (error == (int) DB_RECORD_NOT_FOUND) {
+	} else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) {
 
-    		return(HA_ERR_NO_ACTIVE_RECORD);
+		return(HA_ERR_FOREIGN_DUPLICATE_KEY);
 
- 	} else if (error == (int) DB_ERROR) {
+	} else if (error == (int) DB_RECORD_NOT_FOUND) {
 
-    		return(-1); /* unspecified error */
+		return(HA_ERR_NO_ACTIVE_RECORD);
 
- 	} else if (error == (int) DB_DEADLOCK) {
- 		/* Since we rolled back the whole transaction, we must
- 		tell it also to MySQL so that MySQL knows to empty the
- 		cached binlog for this transaction */
+	} else if (error == (int) DB_ERROR) {
 
- 		if (thd) {
- 			ha_rollback(thd);
- 		}
+		return(-1); /* unspecified error */
 
-    		return(HA_ERR_LOCK_DEADLOCK);
+	} else if (error == (int) DB_DEADLOCK) {
+		/* Since we rolled back the whole transaction, we must
+		tell it also to MySQL so that MySQL knows to empty the
+		cached binlog for this transaction */
 
- 	} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
+		if (thd) {
+			ha_rollback(thd);
+		}
+
+		return(HA_ERR_LOCK_DEADLOCK);
+
+	} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
 
 		/* Starting from 5.0.13, we let MySQL just roll back the
 		latest SQL statement in a lock wait timeout. Previously, we
@@ -471,52 +474,52 @@
 			ha_rollback(thd);
 		}
 
-   		return(HA_ERR_LOCK_WAIT_TIMEOUT);
+		return(HA_ERR_LOCK_WAIT_TIMEOUT);
 
- 	} else if (error == (int) DB_NO_REFERENCED_ROW) {
+	} else if (error == (int) DB_NO_REFERENCED_ROW) {
 
-    		return(HA_ERR_NO_REFERENCED_ROW);
+		return(HA_ERR_NO_REFERENCED_ROW);
 
- 	} else if (error == (int) DB_ROW_IS_REFERENCED) {
+	} else if (error == (int) DB_ROW_IS_REFERENCED) {
 
-    		return(HA_ERR_ROW_IS_REFERENCED);
+		return(HA_ERR_ROW_IS_REFERENCED);
 
-        } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
+	} else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
 
-    		return(HA_ERR_CANNOT_ADD_FOREIGN);
+		return(HA_ERR_CANNOT_ADD_FOREIGN);
 
-        } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
+	} else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
 
-    		return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
+		return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
 						misleading, a new MySQL error
 						code should be introduced */
-        } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
+	} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
 
-    		return(HA_ERR_CRASHED);
+		return(HA_ERR_CRASHED);
 
- 	} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
+	} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
 
-    		return(HA_ERR_RECORD_FILE_FULL);
+		return(HA_ERR_RECORD_FILE_FULL);
 
- 	} else if (error == (int) DB_TABLE_IS_BEING_USED) {
+	} else if (error == (int) DB_TABLE_IS_BEING_USED) {
 
-    		return(HA_ERR_WRONG_COMMAND);
+		return(HA_ERR_WRONG_COMMAND);
 
- 	} else if (error == (int) DB_TABLE_NOT_FOUND) {
+	} else if (error == (int) DB_TABLE_NOT_FOUND) {
 
-    		return(HA_ERR_KEY_NOT_FOUND);
+		return(HA_ERR_KEY_NOT_FOUND);
 
-  	} else if (error == (int) DB_TOO_BIG_RECORD) {
+	} else if (error == (int) DB_TOO_BIG_RECORD) {
 
-    		return(HA_ERR_TO_BIG_ROW);
+		return(HA_ERR_TO_BIG_ROW);
 
-  	} else if (error == (int) DB_CORRUPTION) {
+	} else if (error == (int) DB_CORRUPTION) {
 
-    		return(HA_ERR_CRASHED);
-  	} else if (error == (int) DB_NO_SAVEPOINT) {
+		return(HA_ERR_CRASHED);
+	} else if (error == (int) DB_NO_SAVEPOINT) {
 
-    		return(HA_ERR_NO_SAVEPOINT);
-  	} else if (error == (int) DB_LOCK_TABLE_FULL) {
+		return(HA_ERR_NO_SAVEPOINT);
+	} else if (error == (int) DB_LOCK_TABLE_FULL) {
  		/* Since we rolled back the whole transaction, we must
  		tell it also to MySQL so that MySQL knows to empty the
  		cached binlog for this transaction */
@@ -568,21 +571,21 @@
 void
 innobase_mysql_print_thd(
 /*=====================*/
-	FILE*   f,		/* in: output stream */
-	void*   input_thd,	/* in: pointer to a MySQL THD object */
+	FILE*	f,		/* in: output stream */
+	void*	input_thd,	/* in: pointer to a MySQL THD object */
 	uint	max_query_len)	/* in: max query length to print, or 0 to
 				   use the default max length */
 {
 	const THD*	thd;
-        const Security_context *sctx;
+	const Security_context *sctx;
 	const char*	s;
 
-        thd = (const THD*) input_thd;
-        /* We probably want to have original user as part of debug output. */
-        sctx = &thd->main_security_ctx;
+	thd = (const THD*) input_thd;
+	/* We probably want to have original user as part of debug output. */
+	sctx = &thd->main_security_ctx;
 
 
-  	fprintf(f, "MySQL thread id %lu, query id %lu",
+	fprintf(f, "MySQL thread id %lu, query id %lu",
 		thd->thread_id, (ulong) thd->query_id);
 	if (sctx->host) {
 		putc(' ', f);
@@ -594,10 +597,10 @@
 		fputs(sctx->ip, f);
 	}
 
-        if (sctx->user) {
+	if (sctx->user) {
 		putc(' ', f);
 		fputs(sctx->user, f);
-  	}
+	}
 
 	if ((s = thd->proc_info)) {
 		putc(' ', f);
@@ -617,8 +620,7 @@
 		/* 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
@@ -630,20 +632,18 @@
 
 		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;
 		}
 
-                /* Use strmake to reduce the timeframe for a race,
-                   compared to fwrite() */
+		/* Use strmake to reduce the timeframe for a race,
+		   compared to fwrite() */
 		len = (uint) (strmake(str, s, len) - str);
 		putc('\n', f);
 		fwrite(str, 1, len, f);
 
-		if (dyn_str)
-		{
+		if (dyn_str) {
 			my_free(dyn_str, MYF(0));
 		}
 	}
@@ -680,6 +680,61 @@
 }
 
 /**********************************************************************
+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
@@ -709,6 +764,21 @@
 	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"
@@ -745,16 +815,35 @@
 		if (fd2 < 0) {
 			DBUG_PRINT("error",("Got error %d on dup",fd2));
 			my_errno=errno;
-                        my_error(EE_OUT_OF_FILERESOURCES,
-                                 MYF(ME_BELL+ME_WAITTANG),
-                                 filename, my_errno);
-                }
+			my_error(EE_OUT_OF_FILERESOURCES,
+				 MYF(ME_BELL+ME_WAITTANG),
+				 filename, my_errno);
+		}
 		my_close(fd, MYF(MY_WME));
 	}
 	return(fd2);
 }
 
 /*************************************************************************
+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. */
@@ -763,30 +852,31 @@
 check_trx_exists(
 /*=============*/
 			/* out: InnoDB transaction handle */
+	handlerton*	hton,	/* in: handlerton for innodb */
 	THD*	thd)	/* in: user thread handle */
 {
 	trx_t*	trx;
 
 	ut_ad(thd == current_thd);
 
-        trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*) thd->ha_data[hton->slot];
 
 	if (trx == NULL) {
-	        DBUG_ASSERT(thd != NULL);
+		DBUG_ASSERT(thd != NULL);
 		trx = trx_allocate_for_mysql();
 
 		trx->mysql_thd = thd;
 		trx->mysql_query_str = &(thd->query);
-                trx->active_trans = 0;
+		trx->active_trans = 0;
 
 		/* Update the info whether we should skip XA steps that eat
 		CPU time */
 		trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
 
-                thd->ha_data[innobase_hton.slot] = trx;
+		thd->ha_data[hton->slot] = trx;
 	} else {
 		if (trx->magic_n != TRX_MAGIC_N) {
-			mem_analyze_corruption((byte*)trx);
+			mem_analyze_corruption(trx);
 
 			ut_a(0);
 		}
@@ -811,16 +901,16 @@
 /*************************************************************************
 Construct ha_innobase handler. */
 
-ha_innobase::ha_innobase(TABLE *table_arg)
-  :handler(&innobase_hton, table_arg),
+ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg)
+  :handler(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_IN_READ_INDEX |
-                  HA_CAN_GEOMETRY |
-                  HA_TABLE_SCAN_ON_INDEX),
+		  HA_NULL_IN_KEY |
+		  HA_CAN_INDEX_BLOBS |
+		  HA_CAN_SQL_HANDLER |
+		  HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
+		  HA_PRIMARY_KEY_IN_READ_INDEX |
+		  HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
+		  HA_TABLE_SCAN_ON_INDEX),
   start_of_scan(0),
   num_write_row(0)
 {}
@@ -839,7 +929,7 @@
 	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 	trx_t*		trx;
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(ht, thd);
 
 	if (prebuilt->trx != trx) {
 
@@ -860,10 +950,11 @@
 void
 innobase_register_stmt(
 /*===================*/
+        handlerton*	hton,	/* in: Innobase hton */
 	THD*	thd)	/* in: MySQL thd (connection) object */
 {
-        /* Register the statement */
-        trans_register_ha(thd, FALSE, &innobase_hton);
+	/* Register the statement */
+	trans_register_ha(thd, FALSE, hton);
 }
 
 /*************************************************************************
@@ -877,18 +968,19 @@
 void
 innobase_register_trx_and_stmt(
 /*===========================*/
+        handlerton *hton, /* in: Innobase handlerton */
 	THD*	thd)	/* in: MySQL thd (connection) object */
 {
 	/* NOTE that actually innobase_register_stmt() registers also
 	the transaction in the AUTOCOMMIT=1 mode. */
 
-	innobase_register_stmt(thd);
+	innobase_register_stmt(hton, thd);
 
-        if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+	if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
-              /* No autocommit mode, register for a transaction */
-              trans_register_ha(thd, TRUE, &innobase_hton);
-        }
+		/* No autocommit mode, register for a transaction */
+		trans_register_ha(thd, TRUE, hton);
+	}
 }
 
 /*   BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
@@ -968,7 +1060,7 @@
 				name */
 	uint	full_name_len,	/* in: length of the full name, i.e.
 				len(dbname) + len(tablename) + 1 */
-        ulonglong *unused)      /* unused for this engine */
+	ulonglong *unused)	/* unused for this engine */
 {
 	ibool	is_autocommit;
 	trx_t*	trx;
@@ -983,7 +1075,7 @@
 		return((my_bool)FALSE);
 	}
 
-        trx = check_trx_exists(thd);
+	trx = check_trx_exists(legacy_innodb_hton, thd);
 	if (trx->has_search_latch) {
 		ut_print_timestamp(stderr);
 		sql_print_error("The calling thread is holding the adaptive "
@@ -1040,11 +1132,11 @@
 	/* The call of row_search_.. will start a new transaction if it is
 	not yet started */
 
-        if (trx->active_trans == 0) {
+	if (trx->active_trans == 0) {
 
-                innobase_register_trx_and_stmt(thd);
-                trx->active_trans = 1;
-        }
+		innobase_register_trx_and_stmt(legacy_innodb_hton, thd);
+		trx->active_trans = 1;
+	}
 
 	if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
 
@@ -1088,23 +1180,70 @@
 }
 
 /*********************************************************************
-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);
+	}
+
+	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);
 	}
-	return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
-						name, (int) namelen));
+
+	my_free(qname, MYF(MY_ALLOW_ZERO_PTR));
 }
 
 /**************************************************************************
@@ -1119,18 +1258,6 @@
 	return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed);
 }
 
-/**************************************************************************
-Obtain a pointer to the MySQL THD object, as in current_thd().  This
-definition must match the one in sql/ha_innodb.cc! */
-extern "C"
-void*
-innobase_current_thd(void)
-/*======================*/
-			/* out: MySQL THD object */
-{
-	return(current_thd);
-}
-
 /*********************************************************************
 Call this when you have opened a new table handle in HANDLER, before you
 call index_read_idx() etc. Actually, we can let the cursor stay open even
@@ -1142,58 +1269,58 @@
 ha_innobase::init_table_handle_for_HANDLER(void)
 /*============================================*/
 {
-        row_prebuilt_t* prebuilt;
+	row_prebuilt_t* prebuilt;
 
-        /* If current thd does not yet have a trx struct, create one.
-        If the current handle does not yet have a prebuilt struct, create
-        one. Update the trx pointers in the prebuilt struct. Normally
-        this operation is done in external_lock. */
+	/* If current thd does not yet have a trx struct, create one.
+	If the current handle does not yet have a prebuilt struct, create
+	one. Update the trx pointers in the prebuilt struct. Normally
+	this operation is done in external_lock. */
 
-        update_thd(current_thd);
+	update_thd(current_thd);
 
-        /* Initialize the prebuilt struct much like it would be inited in
-        external_lock */
+	/* Initialize the prebuilt struct much like it would be inited in
+	external_lock */
 
-        prebuilt = (row_prebuilt_t*)innobase_prebuilt;
+	prebuilt = (row_prebuilt_t*)innobase_prebuilt;
 
 	innobase_release_stat_resources(prebuilt->trx);
 
-        /* If the transaction is not started yet, start it */
+	/* If the transaction is not started yet, start it */
 
-        trx_start_if_not_started_noninline(prebuilt->trx);
+	trx_start_if_not_started_noninline(prebuilt->trx);
 
-        /* Assign a read view if the transaction does not have it yet */
+	/* Assign a read view if the transaction does not have it yet */
 
-        trx_assign_read_view(prebuilt->trx);
+	trx_assign_read_view(prebuilt->trx);
 
 	/* Set the MySQL flag to mark that there is an active transaction */
 
-        if (prebuilt->trx->active_trans == 0) {
+	if (prebuilt->trx->active_trans == 0) {
 
-                innobase_register_trx_and_stmt(current_thd);
+		innobase_register_trx_and_stmt(ht, current_thd);
 
-                prebuilt->trx->active_trans = 1;
-        }
+		prebuilt->trx->active_trans = 1;
+	}
 
-        /* We did the necessary inits in this function, no need to repeat them
-        in row_search_for_mysql */
+	/* We did the necessary inits in this function, no need to repeat them
+	in row_search_for_mysql */
 
-        prebuilt->sql_stat_start = FALSE;
+	prebuilt->sql_stat_start = FALSE;
 
-        /* We let HANDLER always to do the reads as consistent reads, even
-        if the trx isolation level would have been specified as SERIALIZABLE */
+	/* We let HANDLER always to do the reads as consistent reads, even
+	if the trx isolation level would have been specified as SERIALIZABLE */
 
-        prebuilt->select_lock_type = LOCK_NONE;
-        prebuilt->stored_select_lock_type = LOCK_NONE;
+	prebuilt->select_lock_type = LOCK_NONE;
+	prebuilt->stored_select_lock_type = LOCK_NONE;
 
-        /* Always fetch all columns in the index record */
+	/* Always fetch all columns in the index record */
 
-        prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
+	prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
 
-        /* We want always to fetch all columns in the whole row? Or do
+	/* We want always to fetch all columns in the whole row? Or do
 	we???? */
 
-        prebuilt->read_just_key = FALSE;
+	prebuilt->read_just_key = FALSE;
 
 	prebuilt->used_in_HANDLER = TRUE;
 
@@ -1203,23 +1330,67 @@
 /*************************************************************************
 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;
 	bool		ret;
-	char 	        *default_path;
+	char		*default_path;
 
-  	DBUG_ENTER("innobase_init");
+	DBUG_ENTER("innobase_init");
+        handlerton *innobase_hton= (handlerton *)p;
+        legacy_innodb_hton= innobase_hton;
+
+        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;
+	 if (have_innodb != SHOW_OPTION_YES)
+	   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) {
@@ -1239,7 +1410,7 @@
 		}
 	}
 
-  	os_innodb_umask = (ulint)my_umask;
+	os_innodb_umask = (ulint)my_umask;
 
 	/* First calculate the default path for innodb_data_home_dir etc.,
 	in case the user has not given any value.
@@ -1251,20 +1422,20 @@
 		default_path = mysql_real_data_home;
 		fil_path_to_mysql_datadir = mysql_real_data_home;
 	} else {
-	  	/* It's better to use current lib, to keep paths short */
-	  	current_dir[0] = FN_CURLIB;
-	  	current_dir[1] = FN_LIBCHAR;
-	  	current_dir[2] = 0;
-	  	default_path = current_dir;
+		/* It's better to use current lib, to keep paths short */
+		current_dir[0] = FN_CURLIB;
+		current_dir[1] = FN_LIBCHAR;
+		current_dir[2] = 0;
+		default_path = current_dir;
 	}
 
 	ut_a(default_path);
 
 	if (specialflag & SPECIAL_NO_PRIOR) {
-	        srv_set_thread_priorities = FALSE;
+		srv_set_thread_priorities = FALSE;
 	} else {
-	        srv_set_thread_priorities = TRUE;
-	        srv_query_thread_priority = QUERY_PRIOR;
+		srv_set_thread_priorities = TRUE;
+		srv_query_thread_priority = QUERY_PRIOR;
 	}
 
 	/* Set InnoDB initialization parameters according to the values
@@ -1278,11 +1449,11 @@
 			 default_path);
 
 	/* Set default InnoDB data file size to 10 MB and let it be
-  	auto-extending. Thus users can use InnoDB in >= 4.0 without having
+	auto-extending. Thus users can use InnoDB in >= 4.0 without having
 	to specify any startup options. */
 
 	if (!innobase_data_file_path) {
-  		innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
+		innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
 	}
 
 	/* Since InnoDB edits the argument in the next call, we make another
@@ -1300,11 +1471,11 @@
 				&srv_auto_extend_last_data_file,
 				&srv_last_file_size_max);
 	if (ret == FALSE) {
-	  	sql_print_error(
+		sql_print_error(
 			"InnoDB: syntax error in innodb_data_file_path");
-	  	my_free(internal_innobase_data_file_path,
+		my_free(internal_innobase_data_file_path,
 						MYF(MY_ALLOW_ZERO_PTR));
-                goto error;
+		goto error;
 	}
 
 	/* -------------- Log files ---------------------------*/
@@ -1312,7 +1483,7 @@
 	/* The default dir for log files is the datadir of MySQL */
 
 	if (!innobase_log_group_home_dir) {
-	  	innobase_log_group_home_dir = default_path;
+		innobase_log_group_home_dir = default_path;
 	}
 
 #ifdef UNIV_LOG_ARCHIVE
@@ -1333,9 +1504,9 @@
 	  sql_print_error("syntax error in innodb_log_group_home_dir, or a "
 			  "wrong number of mirrored log groups");
 
-	  	my_free(internal_innobase_data_file_path,
+		my_free(internal_innobase_data_file_path,
 						MYF(MY_ALLOW_ZERO_PTR));
-                goto error;
+		goto error;
 	}
 
 	/* --------------------------------------------------*/
@@ -1351,25 +1522,25 @@
 #endif /* UNIV_LOG_ARCHIVE */
 	srv_log_buffer_size = (ulint) innobase_log_buffer_size;
 
-        /* We set srv_pool_size here in units of 1 kB. InnoDB internally
-        changes the value so that it becomes the number of database pages. */
+	/* We set srv_pool_size here in units of 1 kB. InnoDB internally
+	changes the value so that it becomes the number of database pages. */
 
-        if (innobase_buffer_pool_awe_mem_mb == 0) {
-                /* Careful here: we first convert the signed long int to ulint
-                and only after that divide */
-
-                srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
-        } else {
-                srv_use_awe = TRUE;
-                srv_pool_size = (ulint)
-                                (1024 * innobase_buffer_pool_awe_mem_mb);
-                srv_awe_window_size = (ulint) innobase_buffer_pool_size;
-
-                /* Note that what the user specified as
-                innodb_buffer_pool_size is actually the AWE memory window
-                size in this case, and the real buffer pool size is
-                determined by .._awe_mem_mb. */
-        }
+	if (innobase_buffer_pool_awe_mem_mb == 0) {
+		/* Careful here: we first convert the signed long int to ulint
+		and only after that divide */
+
+		srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
+	} else {
+		srv_use_awe = TRUE;
+		srv_pool_size = (ulint)
+				(1024 * innobase_buffer_pool_awe_mem_mb);
+		srv_awe_window_size = (ulint) innobase_buffer_pool_size;
+
+		/* Note that what the user specified as
+		innodb_buffer_pool_size is actually the AWE memory window
+		size in this case, and the real buffer pool size is
+		determined by .._awe_mem_mb. */
+	}
 
 	srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
 
@@ -1387,7 +1558,7 @@
 	row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
 
 	srv_file_per_table = (ibool) innobase_file_per_table;
-        srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
+	srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
 
 	srv_max_n_open_files = (ulint) innobase_open_files;
 	srv_innodb_status = (ibool) innobase_create_status_file;
@@ -1413,7 +1584,7 @@
 	memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256);
 
 	/* Since we in this module access directly the fields of a trx
-        struct, and due to different headers and flags it might happen that
+	struct, and due to different headers and flags it might happen that
 	mutex_t has a different size in this module and in InnoDB
 	modules, we check at run time that the size is the same in
 	these compilation modules. */
@@ -1423,46 +1594,31 @@
 	err = innobase_start_or_create_for_mysql();
 
 	if (err != DB_SUCCESS) {
-	  	my_free(internal_innobase_data_file_path,
+		my_free(internal_innobase_data_file_path,
 						MYF(MY_ALLOW_ZERO_PTR));
-                goto error;
+		goto error;
 	}
 
 	(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
-			 		(hash_get_key) innobase_get_key, 0, 0);
-        pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
-        pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
-        pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
-        pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
-        pthread_cond_init(&commit_cond, NULL);
+					(hash_get_key) innobase_get_key, 0, 0);
+	pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
+	pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
+	pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
+	pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
+	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
-        DBUG_RETURN(TRUE);
+	have_innodb= SHOW_OPTION_DISABLED;	// If we couldn't use handler
+	DBUG_RETURN(TRUE);
 }
 
 /***********************************************************************
 Closes an InnoDB database. */
 
-bool
-innobase_end(void)
+int
+innobase_end(handlerton *hton, ha_panic_function type)
 /*==============*/
 				/* out: TRUE if error */
 {
@@ -1470,29 +1626,29 @@
 
 	DBUG_ENTER("innobase_end");
 
-#ifdef __NETWARE__ 	/* some special cleanup for NetWare */
+#ifdef __NETWARE__	/* some special cleanup for NetWare */
 	if (nw_panic) {
 		set_panic_flag_for_netware();
 	}
 #endif
 	if (innodb_inited) {
 
-	        srv_fast_shutdown = (ulint) innobase_fast_shutdown;
-	  	innodb_inited = 0;
-	  	if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
-	    		err = 1;
+		srv_fast_shutdown = (ulint) innobase_fast_shutdown;
+		innodb_inited = 0;
+		if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
+			err = 1;
 		}
-	  	hash_free(&innobase_open_tables);
-	  	my_free(internal_innobase_data_file_path,
+		hash_free(&innobase_open_tables);
+		my_free(internal_innobase_data_file_path,
 						MYF(MY_ALLOW_ZERO_PTR));
-                pthread_mutex_destroy(&innobase_share_mutex);
-                pthread_mutex_destroy(&prepare_commit_mutex);
-                pthread_mutex_destroy(&commit_threads_m);
-                pthread_mutex_destroy(&commit_cond_m);
-                pthread_cond_destroy(&commit_cond);
+		pthread_mutex_destroy(&innobase_share_mutex);
+		pthread_mutex_destroy(&prepare_commit_mutex);
+		pthread_mutex_destroy(&commit_threads_m);
+		pthread_mutex_destroy(&commit_cond_m);
+		pthread_cond_destroy(&commit_cond);
 	}
 
-  	DBUG_RETURN(err);
+	DBUG_RETURN(err);
 }
 
 /********************************************************************
@@ -1500,17 +1656,17 @@
 the logs, and the name of this function should be innobase_checkpoint. */
 
 bool
-innobase_flush_logs(void)
+innobase_flush_logs(handlerton *hton)
 /*=====================*/
 				/* out: TRUE if error */
 {
-  	bool 	result = 0;
+	bool	result = 0;
 
-  	DBUG_ENTER("innobase_flush_logs");
+	DBUG_ENTER("innobase_flush_logs");
 
 	log_buffer_flush_to_disk();
 
-  	DBUG_RETURN(result);
+	DBUG_RETURN(result);
 }
 
 /*********************************************************************
@@ -1521,23 +1677,10 @@
 /*================*/
 	trx_t*	trx)	/* in: transaction handle */
 {
-        if (trx->conc_state == TRX_NOT_STARTED) {
+	if (trx->conc_state == TRX_NOT_STARTED) {
 
-                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 */
+		return;
+	}
 
 	trx_commit_for_mysql(trx);
 }
@@ -1552,16 +1695,17 @@
 innobase_start_trx_and_assign_read_view(
 /*====================================*/
 			/* out: 0 */
+        handlerton *hton, /* in: Innodb handlerton */ 
 	THD*	thd)	/* in: MySQL thread handle of the user for whom
 			the transaction should be committed */
 {
 	trx_t*	trx;
 
-  	DBUG_ENTER("innobase_start_trx_and_assign_read_view");
+	DBUG_ENTER("innobase_start_trx_and_assign_read_view");
 
 	/* Create a new trx struct for thd, if it does not yet have one */
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(hton, thd);
 
 	/* This is just to play safe: release a possible FIFO ticket and
 	search latch. Since we will reserve the kernel mutex, we have to
@@ -1579,12 +1723,10 @@
 
 	/* Set the MySQL flag to mark that there is an active transaction */
 
-        if (trx->active_trans == 0) {
-
-                innobase_register_trx_and_stmt(current_thd);
-
-                trx->active_trans = 1;
-        }
+	if (trx->active_trans == 0) {
+		innobase_register_trx_and_stmt(hton, current_thd);
+		trx->active_trans = 1;
+	}
 
 	DBUG_RETURN(0);
 }
@@ -1597,17 +1739,18 @@
 innobase_commit(
 /*============*/
 			/* out: 0 */
-	THD*	thd,	/* in: MySQL thread handle of the user for whom
+        handlerton *hton, /* in: Innodb handlerton */ 
+	THD* 	thd,	/* in: MySQL thread handle of the user for whom
 			the transaction should be committed */
-        bool    all)    /* in: TRUE - commit transaction
-                               FALSE - the current SQL statement ended */
+	bool	all)	/* in:	TRUE - commit transaction
+				FALSE - the current SQL statement ended */
 {
 	trx_t*		trx;
 
-  	DBUG_ENTER("innobase_commit");
-  	DBUG_PRINT("trans", ("ending transaction"));
+	DBUG_ENTER("innobase_commit");
+	DBUG_PRINT("trans", ("ending transaction"));
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(hton, thd);
 
 	/* Update the info whether we should skip XA steps that eat CPU time */
 	trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
@@ -1616,11 +1759,11 @@
 	reserve the kernel mutex, we have to release the search system latch
 	first to obey the latching order. */
 
-        if (trx->has_search_latch) {
-                          trx_search_latch_release_if_reserved(trx);
-        }
+	if (trx->has_search_latch) {
+			  trx_search_latch_release_if_reserved(trx);
+	}
 
-        /* The flag trx->active_trans is set to 1 in
+	/* The flag trx->active_trans is set to 1 in
 
 	1. ::external_lock(),
 	2. ::start_stmt(),
@@ -1635,59 +1778,60 @@
 	For the time being, we play safe and do the cleanup though there should
 	be nothing to clean up. */
 
-        if (trx->active_trans == 0
-	    && trx->conc_state != TRX_NOT_STARTED) {
+	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)))) {
+	if (all
+		|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
 
- 		/* We were instructed to commit the whole transaction, or
+		/* We were instructed to commit the whole transaction, or
 		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 */
+		/* We need current binlog position for ibbackup to work.
+		Note, the position is current because of
+		prepare_commit_mutex */
 retry:
-                if (srv_commit_concurrency > 0)
-                {
-                  pthread_mutex_lock(&commit_cond_m);
-                  commit_threads++;
-                  if (commit_threads > srv_commit_concurrency)
-                  {
-                    commit_threads--;
-                    pthread_cond_wait(&commit_cond, &commit_cond_m);
-                    pthread_mutex_unlock(&commit_cond_m);
-                    goto retry;
-                  }
-                  else
-                    pthread_mutex_unlock(&commit_cond_m);
-                }
-
-                trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
-                trx->mysql_log_offset =
-                        (ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
+		if (srv_commit_concurrency > 0) {
+			pthread_mutex_lock(&commit_cond_m);
+			commit_threads++;
+
+			if (commit_threads > srv_commit_concurrency) {
+				commit_threads--;
+				pthread_cond_wait(&commit_cond,
+					&commit_cond_m);
+				pthread_mutex_unlock(&commit_cond_m);
+				goto retry;
+			}
+			else {
+				pthread_mutex_unlock(&commit_cond_m);
+			}
+		}
+
+		trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
+		trx->mysql_log_offset =
+			(ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
 
 		innobase_commit_low(trx);
 
-                if (srv_commit_concurrency > 0)
-                {
-                  pthread_mutex_lock(&commit_cond_m);
-                  commit_threads--;
-                  pthread_cond_signal(&commit_cond);
-                  pthread_mutex_unlock(&commit_cond_m);
-                }
+		if (srv_commit_concurrency > 0) {
+			pthread_mutex_lock(&commit_cond_m);
+			commit_threads--;
+			pthread_cond_signal(&commit_cond);
+			pthread_mutex_unlock(&commit_cond_m);
+		}
 
-                if (trx->active_trans == 2) {
+		if (trx->active_trans == 2) {
 
-                        pthread_mutex_unlock(&prepare_commit_mutex);
-                }
+			pthread_mutex_unlock(&prepare_commit_mutex);
+		}
 
-                trx->active_trans = 0;
+		trx->active_trans = 0;
 
 	} else {
-	        /* We just mark the SQL statement ended and do not do a
+		/* We just mark the SQL statement ended and do not do a
 		transaction commit */
 
 		if (trx->auto_inc_lock) {
@@ -1705,11 +1849,11 @@
 
 	/* Tell the InnoDB server that there might be work for utility
 	threads: */
-        if (trx->declared_to_be_inside_innodb) {
-                          /* Release our possible ticket in the FIFO */
+	if (trx->declared_to_be_inside_innodb) {
+			  /* Release our possible ticket in the FIFO */
 
-                          srv_conc_force_exit_innodb(trx);
-        }
+			  srv_conc_force_exit_innodb(trx);
+	}
 	srv_active_wake_master_thread();
 
 	DBUG_RETURN(0);
@@ -1731,12 +1875,13 @@
 int
 innobase_report_binlog_offset_and_commit(
 /*=====================================*/
-                                /* out: 0 */
-        THD*    thd,            /* in: user thread */
-        void*   trx_handle,     /* in: InnoDB trx handle */
-        char*   log_file_name,  /* in: latest binlog file name */
-        my_off_t end_offset)    /* in: the offset in the binlog file
-                                   up to which we wrote */
+				/* out: 0 */
+        handlerton *hton, /* in: Innodb handlerton */ 
+	THD*	thd,		/* in: user thread */
+	void*	trx_handle,	/* in: InnoDB trx handle */
+	char*	log_file_name,	/* in: latest binlog file name */
+	my_off_t end_offset)	/* in: the offset in the binlog file
+				   up to which we wrote */
 {
 	trx_t*	trx;
 
@@ -1749,7 +1894,7 @@
 
 	trx->flush_log_later = TRUE;
 
-	innobase_commit(thd, TRUE);
+	innobase_commit(hton, thd, TRUE);
 
 	trx->flush_log_later = FALSE;
 
@@ -1763,26 +1908,26 @@
 void
 innobase_store_binlog_offset_and_flush_log(
 /*=======================================*/
-    char *binlog_name,          /* in: binlog name */
-    longlong	offset)		/* in: binlog offset */
+	char*		binlog_name,	/* in: binlog name */
+	longlong	offset)		/* in: binlog offset */
 {
 	mtr_t mtr;
 
 	assert(binlog_name != NULL);
 
 	/* Start a mini-transaction */
-        mtr_start_noninline(&mtr);
+	mtr_start_noninline(&mtr);
 
 	/* Update the latest MySQL binlog name and offset info
-        in trx sys header */
+	in trx sys header */
 
-        trx_sys_update_mysql_binlog_offset(
-            binlog_name,
-            offset,
-            TRX_SYS_MYSQL_LOG_INFO, &mtr);
+	trx_sys_update_mysql_binlog_offset(
+		binlog_name,
+		offset,
+		TRX_SYS_MYSQL_LOG_INFO, &mtr);
 
-        /* Commits the mini-transaction */
-        mtr_commit(&mtr);
+	/* Commits the mini-transaction */
+	mtr_commit(&mtr);
 
 	/* Synchronous flush of the log buffer to disk */
 	log_buffer_flush_to_disk();
@@ -1796,24 +1941,25 @@
 int
 innobase_commit_complete(
 /*=====================*/
-                                /* out: 0 */
-        THD*    thd)            /* in: user thread */
+				/* out: 0 */
+        handlerton *hton, /* in: Innodb handlerton */ 
+	THD*	thd)		/* in: user thread */
 {
 	trx_t*	trx;
 
-        trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*) thd->ha_data[hton->slot];
 
-        if (trx && trx->active_trans) {
+	if (trx && trx->active_trans) {
 
-                trx->active_trans = 0;
+		trx->active_trans = 0;
 
-                if (UNIV_UNLIKELY(srv_flush_log_at_trx_commit == 0)) {
+		if (UNIV_UNLIKELY(srv_flush_log_at_trx_commit == 0)) {
 
-                        return(0);
-                }
+			return(0);
+		}
 
-                trx_commit_complete_for_mysql(trx);
-        }
+		trx_commit_complete_for_mysql(trx);
+	}
 
 	return(0);
 }
@@ -1825,10 +1971,11 @@
 innobase_rollback(
 /*==============*/
 			/* out: 0 or error number */
+        handlerton *hton, /* in: Innodb handlerton */ 
 	THD*	thd,	/* in: handle to the MySQL thread of the user
 			whose transaction should be rolled back */
-        bool    all)    /* in: TRUE - commit transaction
-                               FALSE - the current SQL statement ended */
+	bool	all)	/* in:	TRUE - commit transaction
+				FALSE - the current SQL statement ended */
 {
 	int	error = 0;
 	trx_t*	trx;
@@ -1836,7 +1983,7 @@
 	DBUG_ENTER("innobase_rollback");
 	DBUG_PRINT("trans", ("aborting transaction"));
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(hton, thd);
 
 	/* Update the info whether we should skip XA steps that eat CPU time */
 	trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
@@ -1847,7 +1994,7 @@
 
 	innobase_release_stat_resources(trx);
 
-        if (trx->auto_inc_lock) {
+	if (trx->auto_inc_lock) {
 		/* If we had reserved the auto-inc lock for some table (if
 		we come here to roll back the latest SQL statement) we
 		release it now before a possibly lengthy rollback */
@@ -1855,11 +2002,11 @@
 		row_unlock_table_autoinc_for_mysql(trx);
 	}
 
-        if (all
-	    || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
+	if (all
+		|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
 
 		error = trx_rollback_for_mysql(trx);
-                trx->active_trans = 0;
+		trx->active_trans = 0;
 	} else {
 		error = trx_rollback_last_sql_stat_for_mysql(trx);
 	}
@@ -1887,7 +2034,7 @@
 
 	innobase_release_stat_resources(trx);
 
-        if (trx->auto_inc_lock) {
+	if (trx->auto_inc_lock) {
 		/* If we had reserved the auto-inc lock for some table (if
 		we come here to roll back the latest SQL statement) we
 		release it now before a possibly lengthy rollback */
@@ -1908,18 +2055,19 @@
 /*===========================*/
 				/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
 				no savepoint with the given name */
+        handlerton *hton,       /* in: Innodb handlerton */ 
 	THD*	thd,		/* in: handle to the MySQL thread of the user
 				whose transaction should be rolled back */
-        void *savepoint)        /* in: savepoint data */
+	void*	savepoint)	/* in: savepoint data */
 {
-	ib_longlong mysql_binlog_cache_pos;
-	int	    error = 0;
-	trx_t*	    trx;
-        char 	    name[64];
+	ib_longlong	mysql_binlog_cache_pos;
+	int		error = 0;
+	trx_t*		trx;
+	char		name[64];
 
 	DBUG_ENTER("innobase_rollback_to_savepoint");
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(hton, thd);
 
 	/* Release a possible FIFO ticket and search latch. Since we will
 	reserve the kernel mutex, we have to release the search system latch
@@ -1927,11 +2075,11 @@
 
 	innobase_release_stat_resources(trx);
 
-        /* TODO: use provided savepoint data area to store savepoint data */
+	/* TODO: use provided savepoint data area to store savepoint data */
 
-        longlong2str((ulint)savepoint, name, 36);
+	longlong2str((ulint)savepoint, name, 36);
 
-        error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
+	error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
 						&mysql_binlog_cache_pos);
 	DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 }
@@ -1944,21 +2092,22 @@
 /*=======================*/
 				/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
 				no savepoint with the given name */
+        handlerton*	hton,	/* in: handlerton for Innodb */
 	THD*	thd,		/* in: handle to the MySQL thread of the user
 				whose transaction should be rolled back */
-        void*	savepoint)      /* in: savepoint data */
+	void*	savepoint)	/* in: savepoint data */
 {
-	int	    error = 0;
-	trx_t*	    trx;
-        char 	    name[64];
+	int		error = 0;
+	trx_t*		trx;
+	char		name[64];
 
 	DBUG_ENTER("innobase_release_savepoint");
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(hton, thd);
 
-        /* TODO: use provided savepoint data area to store savepoint data */
+	/* TODO: use provided savepoint data area to store savepoint data */
 
-        longlong2str((ulint)savepoint, name, 36);
+	longlong2str((ulint)savepoint, name, 36);
 
 	error = (int) trx_release_savepoint_for_mysql(trx, name);
 
@@ -1972,23 +2121,24 @@
 innobase_savepoint(
 /*===============*/
 				/* out: always 0, that is, always succeeds */
+	handlerton*	hton,   /* in: handle to the Innodb handlerton */
 	THD*	thd,		/* in: handle to the MySQL thread */
-        void*	savepoint)      /* in: savepoint data */
+	void*	savepoint)	/* in: savepoint data */
 {
 	int	error = 0;
 	trx_t*	trx;
 
 	DBUG_ENTER("innobase_savepoint");
 
-        /*
-          In the autocommit mode there is no sense to set a savepoint
-          (unless we are in sub-statement), so SQL layer ensures that
-          this method is never called in such situation.
-        */
-        DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
-                    thd->in_sub_stmt);
+	/*
+	  In the autocommit mode there is no sense to set a savepoint
+	  (unless we are in sub-statement), so SQL layer ensures that
+	  this method is never called in such situation.
+	*/
+	DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
+		thd->in_sub_stmt);
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(hton, thd);
 
 	/* Release a possible FIFO ticket and search latch. Since we will
 	reserve the kernel mutex, we have to release the search system latch
@@ -1996,14 +2146,14 @@
 
 	innobase_release_stat_resources(trx);
 
-        /* cannot happen outside of transaction */
-        DBUG_ASSERT(trx->active_trans);
+	/* cannot happen outside of transaction */
+	DBUG_ASSERT(trx->active_trans);
 
-        /* TODO: use provided savepoint data area to store savepoint data */
-        char name[64];
-        longlong2str((ulint)savepoint,name,36);
+	/* TODO: use provided savepoint data area to store savepoint data */
+	char name[64];
+	longlong2str((ulint)savepoint,name,36);
 
-        error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
+	error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
 
 	DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 }
@@ -2015,33 +2165,37 @@
 innobase_close_connection(
 /*======================*/
 			/* out: 0 or error number */
+        handlerton*	hton,	/* in:  innobase handlerton */
 	THD*	thd)	/* in: handle to the MySQL thread of the user
 			whose resources should be free'd */
 {
 	trx_t*	trx;
 
-	trx = (trx_t*)thd->ha_data[innobase_hton.slot];
+	trx = (trx_t*)thd->ha_data[hton->slot];
 
 	ut_a(trx);
 
-        if (trx->active_trans == 0
-	    && trx->conc_state != TRX_NOT_STARTED) {
+	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 "
-                            "InnoDB transaction.  %lu row modifications will "
-                            "roll back.",
-                            (ulong)trx->undo_no.low);
+		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);
 
-        trx_free_for_mysql(trx);
+	thr_local_free(trx->mysql_thread_id);
+	trx_free_for_mysql(trx);
 
 	return(0);
 }
@@ -2061,7 +2215,7 @@
 	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);
@@ -2142,11 +2296,11 @@
 /*==============*/
 					/* out: 1 if error, 0 if success */
 	const char*	name,		/* in: table name */
-	int 		mode,		/* in: not used */
-	uint 		test_if_locked)	/* in: not used */
+	int		mode,		/* in: not used */
+	uint		test_if_locked)	/* in: not used */
 {
 	dict_table_t*	ib_table;
-  	char		norm_name[1000];
+	char		norm_name[1000];
 	THD*		thd;
 
 	DBUG_ENTER("ha_innobase::open");
@@ -2175,20 +2329,20 @@
 				table->s->reclength + table->s->max_key_length
 							+ MAX_REF_PARTS * 3;
 	if (!(mysql_byte*) my_multi_malloc(MYF(MY_WME),
-				     &upd_buff, upd_and_key_val_buff_len,
-				     &key_val_buff, upd_and_key_val_buff_len,
-				     NullS)) {
-	  	free_share(share);
+			&upd_buff, upd_and_key_val_buff_len,
+			&key_val_buff, upd_and_key_val_buff_len,
+			NullS)) {
+		free_share(share);
 
-	  	DBUG_RETURN(1);
-  	}
+		DBUG_RETURN(1);
+	}
 
 	/* Get pointer to a table object in InnoDB dictionary cache */
 
-	ib_table = dict_table_get_and_increment_handle_count(
-				      		     norm_name, NULL);
- 	if (NULL == ib_table) {
-	        ut_print_timestamp(stderr);
+	ib_table = dict_table_get(norm_name, TRUE);
+
+	if (NULL == ib_table) {
+		ut_print_timestamp(stderr);
 		sql_print_error("Cannot find table %s from the internal data "
 				"dictionary\nof InnoDB though the .frm file "
 				"for the table exists. Maybe you\nhave "
@@ -2196,33 +2350,33 @@
 				"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);
-    		my_free((gptr) upd_buff, MYF(0));
-    		my_errno = ENOENT;
+		free_share(share);
+		my_free((gptr) upd_buff, MYF(0));
+		my_errno = ENOENT;
 
-    		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
-  	}
+		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
+	}
 
- 	if (ib_table->ibd_file_missing && !thd->tablespace_op) {
-	        ut_print_timestamp(stderr);
+	if (ib_table->ibd_file_missing && !thd->tablespace_op) {
+		ut_print_timestamp(stderr);
 		sql_print_error("MySQL is trying to open a table handle but "
 				"the .ibd file for\ntable %s does not exist.\n"
 				"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);
-    		my_free((gptr) upd_buff, MYF(0));
-    		my_errno = ENOENT;
+		free_share(share);
+		my_free((gptr) upd_buff, MYF(0));
+		my_errno = ENOENT;
 
 		dict_table_decrement_handle_count(ib_table);
-    		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
-  	}
+		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
+	}
 
 	innobase_prebuilt = row_create_prebuilt(ib_table);
 
@@ -2231,32 +2385,32 @@
 
 	/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
 
- 	primary_key = table->s->primary_key;
+	primary_key = table->s->primary_key;
 	key_used_on_scan = primary_key;
 
 	/* Allocate a buffer for a 'row reference'. A row reference is
 	a string of bytes of length ref_length which uniquely specifies
-        a row in our table. Note that MySQL may also compare two row
-        references for equality by doing a simple memcmp on the strings
-        of length ref_length! */
+	a row in our table. Note that MySQL may also compare two row
+	references for equality by doing a simple memcmp on the strings
+	of length ref_length! */
 
-  	if (!row_table_got_default_clust_index(ib_table)) {
-	        if (primary_key >= MAX_KEY) {
+	if (!row_table_got_default_clust_index(ib_table)) {
+		if (primary_key >= MAX_KEY) {
 		  sql_print_error("Table %s has a primary key in InnoDB data "
 				  "dictionary, but not in MySQL!", name);
 		}
 
 		((row_prebuilt_t*)innobase_prebuilt)
 				->clust_index_was_generated = FALSE;
- 		/* MySQL allocates the buffer for ref. key_info->key_length
+		/* MySQL allocates the buffer for ref. key_info->key_length
 		includes space for all key columns + one byte for each column
 		that may be NULL. ref_length must be as exact as possible to
 		save space, because all row reference buffers are allocated
 		based on ref_length. */
 
-  		ref_length = table->key_info[primary_key].key_length;
+		ref_length = table->key_info[primary_key].key_length;
 	} else {
-	        if (primary_key != MAX_KEY) {
+		if (primary_key != MAX_KEY) {
 		  sql_print_error("Table %s has no primary key in InnoDB data "
 				  "dictionary, but has one in MySQL! If you "
 				  "created the table with a MySQL version < "
@@ -2271,7 +2425,7 @@
 		((row_prebuilt_t*)innobase_prebuilt)
 				->clust_index_was_generated = TRUE;
 
-  		ref_length = DATA_ROW_ID_LEN;
+		ref_length = DATA_ROW_ID_LEN;
 
 		/* If we automatically created the clustered index, then
 		MySQL does not know about it, and MySQL must NOT be aware
@@ -2282,21 +2436,22 @@
 		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 "
-				    "though there is no primary key inside "
-				    "InnoDB.", name, (ulong) key_used_on_scan);
+			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 */
 	thr_lock_data_init(&share->lock,&lock,(void*) 0);
 
-  	info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
+	info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
-  	DBUG_RETURN(0);
+	DBUG_RETURN(0);
 }
 
 uint
@@ -2313,19 +2468,19 @@
 /*====================*/
 				/* out: 0 */
 {
-  	DBUG_ENTER("ha_innobase::close");
+	DBUG_ENTER("ha_innobase::close");
 
 	row_prebuilt_free((row_prebuilt_t*) innobase_prebuilt);
 
-    	my_free((gptr) upd_buff, MYF(0));
-        free_share(share);
+	my_free((gptr) upd_buff, MYF(0));
+	free_share(share);
 
 	/* Tell InnoDB server that there might be work for
 	utility threads: */
 
 	srv_active_wake_master_thread();
 
-  	DBUG_RETURN(0);
+	DBUG_RETURN(0);
 }
 
 /* The following accessor functions should really be inside MySQL code! */
@@ -2346,7 +2501,7 @@
 /******************************************************************
 Checks if a field in a record is SQL NULL. Uses the record format
 information in table to track the null bit in record. */
-inline
+static inline
 uint
 field_in_record_is_null(
 /*====================*/
@@ -2415,7 +2570,7 @@
 {
 	CHARSET_INFO*		charset;
 	enum_field_types	mysql_tp;
-	int                     ret;
+	int			ret;
 
 	DBUG_ASSERT(a_length != UNIV_SQL_NULL);
 	DBUG_ASSERT(b_length != UNIV_SQL_NULL);
@@ -2424,14 +2579,14 @@
 
 	switch (mysql_tp) {
 
-        case MYSQL_TYPE_BIT:
+	case MYSQL_TYPE_BIT:
 	case MYSQL_TYPE_STRING:
 	case MYSQL_TYPE_VAR_STRING:
-	case FIELD_TYPE_TINY_BLOB:
-	case FIELD_TYPE_MEDIUM_BLOB:
-	case FIELD_TYPE_BLOB:
-	case FIELD_TYPE_LONG_BLOB:
-        case MYSQL_TYPE_VARCHAR:
+	case MYSQL_TYPE_TINY_BLOB:
+	case MYSQL_TYPE_MEDIUM_BLOB:
+	case MYSQL_TYPE_BLOB:
+	case MYSQL_TYPE_LONG_BLOB:
+	case MYSQL_TYPE_VARCHAR:
 		/* Use the charset number to pick the right charset struct for
 		the comparison. Since the MySQL function get_charset may be
 		slow before Bar removes the mutex operation there, we first
@@ -2453,21 +2608,21 @@
 			}
 		}
 
-                /* Starting from 4.1.3, we use strnncollsp() in comparisons of
-                non-latin1_swedish_ci strings. NOTE that the collation order
-                changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
-                having indexes on such data need to rebuild their tables! */
-
-                ret = charset->coll->strnncollsp(charset,
-                                  a, a_length,
-                                                 b, b_length, 0);
+		/* Starting from 4.1.3, we use strnncollsp() in comparisons of
+		non-latin1_swedish_ci strings. NOTE that the collation order
+		changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
+		having indexes on such data need to rebuild their tables! */
+
+		ret = charset->coll->strnncollsp(charset,
+				  a, a_length,
+						 b, b_length, 0);
 		if (ret < 0) {
-		        return(-1);
+			return(-1);
 		} else if (ret > 0) {
-		        return(1);
+			return(1);
 		} else {
-		        return(0);
-	        }
+			return(0);
+		}
 	default:
 		assert(0);
 	}
@@ -2494,11 +2649,11 @@
 	8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
 	the type */
 
-	DBUG_ASSERT((ulint)FIELD_TYPE_STRING < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_VAR_STRING < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_DOUBLE < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_FLOAT < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_DECIMAL < 256);
+	DBUG_ASSERT((ulint)MYSQL_TYPE_STRING < 256);
+	DBUG_ASSERT((ulint)MYSQL_TYPE_VAR_STRING < 256);
+	DBUG_ASSERT((ulint)MYSQL_TYPE_DOUBLE < 256);
+	DBUG_ASSERT((ulint)MYSQL_TYPE_FLOAT < 256);
+	DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256);
 
 	if (field->flags & UNSIGNED_FLAG) {
 
@@ -2507,8 +2662,8 @@
 		*unsigned_flag = 0;
 	}
 
-	if (field->real_type() == FIELD_TYPE_ENUM
-	    || field->real_type() == FIELD_TYPE_SET) {
+	if (field->real_type() == MYSQL_TYPE_ENUM
+		|| field->real_type() == MYSQL_TYPE_SET) {
 
 		/* MySQL has field->type() a string type for these, but the
 		data is actually internally stored as an unsigned integer
@@ -2522,58 +2677,58 @@
 	}
 
 	switch (field->type()) {
-	        /* 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()) {
-						return(DATA_BINARY);
-					} else if (strcmp(
-						  field->charset()->name,
-						 "latin1_swedish_ci") == 0) {
-						return(DATA_VARCHAR);
-					} else {
-						return(DATA_VARMYSQL);
-					}
-                case MYSQL_TYPE_BIT:
-		case MYSQL_TYPE_STRING: if (field->binary()) {
-
-						return(DATA_FIXBINARY);
-					} else if (strcmp(
-						   field->charset()->name,
-						   "latin1_swedish_ci") == 0) {
-						return(DATA_CHAR);
-					} else {
-						return(DATA_MYSQL);
-					}
-                case FIELD_TYPE_NEWDECIMAL:
-                                        return(DATA_FIXBINARY);
-		case FIELD_TYPE_LONG:
-		case FIELD_TYPE_LONGLONG:
-		case FIELD_TYPE_TINY:
-		case FIELD_TYPE_SHORT:
-		case FIELD_TYPE_INT24:
-		case FIELD_TYPE_DATE:
-		case FIELD_TYPE_DATETIME:
-		case FIELD_TYPE_YEAR:
-		case FIELD_TYPE_NEWDATE:
-		case FIELD_TYPE_TIME:
-		case FIELD_TYPE_TIMESTAMP:
-					return(DATA_INT);
-		case FIELD_TYPE_FLOAT:
-					return(DATA_FLOAT);
-		case FIELD_TYPE_DOUBLE:
-					return(DATA_DOUBLE);
-		case FIELD_TYPE_DECIMAL:
-					return(DATA_DECIMAL);
-		case FIELD_TYPE_GEOMETRY:
-		case FIELD_TYPE_TINY_BLOB:
-		case FIELD_TYPE_MEDIUM_BLOB:
-		case FIELD_TYPE_BLOB:
-		case FIELD_TYPE_LONG_BLOB:
-					return(DATA_BLOB);
-		default:
-					assert(0);
+		/* 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()) {
+			return(DATA_BINARY);
+		} else if (strcmp(
+				   field->charset()->name,
+				   "latin1_swedish_ci") == 0) {
+			return(DATA_VARCHAR);
+		} else {
+			return(DATA_VARMYSQL);
+		}
+	case MYSQL_TYPE_BIT:
+	case MYSQL_TYPE_STRING: if (field->binary()) {
+
+			return(DATA_FIXBINARY);
+		} else if (strcmp(
+				   field->charset()->name,
+				   "latin1_swedish_ci") == 0) {
+			return(DATA_CHAR);
+		} else {
+			return(DATA_MYSQL);
+		}
+	case MYSQL_TYPE_NEWDECIMAL:
+		return(DATA_FIXBINARY);
+	case MYSQL_TYPE_LONG:
+	case MYSQL_TYPE_LONGLONG:
+	case MYSQL_TYPE_TINY:
+	case MYSQL_TYPE_SHORT:
+	case MYSQL_TYPE_INT24:
+	case MYSQL_TYPE_DATE:
+	case MYSQL_TYPE_DATETIME:
+	case MYSQL_TYPE_YEAR:
+	case MYSQL_TYPE_NEWDATE:
+	case MYSQL_TYPE_TIME:
+	case MYSQL_TYPE_TIMESTAMP:
+		return(DATA_INT);
+	case MYSQL_TYPE_FLOAT:
+		return(DATA_FLOAT);
+	case MYSQL_TYPE_DOUBLE:
+		return(DATA_DOUBLE);
+	case MYSQL_TYPE_DECIMAL:
+		return(DATA_DECIMAL);
+	case MYSQL_TYPE_GEOMETRY:
+	case MYSQL_TYPE_TINY_BLOB:
+	case MYSQL_TYPE_MEDIUM_BLOB:
+	case MYSQL_TYPE_BLOB:
+	case MYSQL_TYPE_LONG_BLOB:
+		return(DATA_BLOB);
+	default:
+		assert(0);
 	}
 
 	return(0);
@@ -2615,21 +2770,21 @@
 ha_innobase::store_key_val_for_row(
 /*===============================*/
 				/* out: key value length as stored in buff */
-	uint 		keynr,	/* in: key number */
+	uint		keynr,	/* in: key number */
 	char*		buff,	/* in/out: buffer for the key value (in MySQL
 				format) */
 	uint		buff_len,/* in: buffer length */
 	const mysql_byte* record)/* in: row in MySQL format */
 {
-	KEY*		key_info 	= table->key_info + keynr;
-  	KEY_PART_INFO*	key_part	= key_info->key_part;
-  	KEY_PART_INFO*	end		= key_part + key_info->key_parts;
+	KEY*		key_info	= table->key_info + keynr;
+	KEY_PART_INFO*	key_part	= key_info->key_part;
+	KEY_PART_INFO*	end		= key_part + key_info->key_parts;
 	char*		buff_start	= buff;
 	enum_field_types mysql_type;
 	Field*		field;
 	ibool		is_null;
 
-  	DBUG_ENTER("store_key_val_for_row");
+	DBUG_ENTER("store_key_val_for_row");
 
 	/* The format for storing a key field in MySQL is the following:
 
@@ -2658,19 +2813,19 @@
 
 	bzero(buff, buff_len);
 
-  	for (; key_part != end; key_part++) {
-	        is_null = FALSE;
+	for (; key_part != end; key_part++) {
+		is_null = FALSE;
 
-    		if (key_part->null_bit) {
-      			if (record[key_part->null_offset]
+		if (key_part->null_bit) {
+			if (record[key_part->null_offset]
 						& key_part->null_bit) {
 				*buff = 1;
 				is_null = TRUE;
-      			} else {
+			} else {
 				*buff = 0;
 			}
 			buff++;
-    		}
+		}
 
 		field = key_part->field;
 		mysql_type = field->type();
@@ -2739,10 +2894,10 @@
 
 			buff += key_len;
 
-		} else if (mysql_type == FIELD_TYPE_TINY_BLOB
-		    || mysql_type == FIELD_TYPE_MEDIUM_BLOB
-		    || mysql_type == FIELD_TYPE_BLOB
-		    || mysql_type == FIELD_TYPE_LONG_BLOB) {
+		} else if (mysql_type == MYSQL_TYPE_TINY_BLOB
+			|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
+			|| mysql_type == MYSQL_TYPE_BLOB
+			|| mysql_type == MYSQL_TYPE_LONG_BLOB) {
 
 			CHARSET_INFO*	cs;
 			ulint		key_len;
@@ -2755,7 +2910,7 @@
 
 			key_len = key_part->length;
 
-		        if (is_null) {
+			if (is_null) {
 				buff += key_len + 2;
 
 				continue;
@@ -2763,7 +2918,7 @@
 
 			cs = field->charset();
 
-		        blob_data = row_mysql_read_blob_ref(&blob_len,
+			blob_data = row_mysql_read_blob_ref(&blob_len,
 				(byte*) (record
 				+ (ulint)get_field_offset(table, field)),
 					(ulint) field->pack_length());
@@ -2771,7 +2926,7 @@
 			true_len = blob_len;
 
 			ut_a(get_field_offset(table, field)
-						     == key_part->offset);
+				== key_part->offset);
 
 			/* For multi byte character sets we need to calculate
 			the true length of the key */
@@ -2822,7 +2977,7 @@
 
 			key_len = key_part->length;
 
-		        if (is_null) {
+			if (is_null) {
 				 buff += key_len;
 
 				 continue;
@@ -2837,8 +2992,8 @@
 			type is not enum or set. For these fields check
 			if character set is multi byte. */
 
-			if (real_type != FIELD_TYPE_ENUM
-				&& real_type != FIELD_TYPE_SET
+			if (real_type != MYSQL_TYPE_ENUM
+				&& real_type != MYSQL_TYPE_SET
 				&& ( mysql_type == MYSQL_TYPE_VAR_STRING
 					|| mysql_type == MYSQL_TYPE_STRING)) {
 
@@ -2875,7 +3030,7 @@
 				buff += pad_len;
 			}
 		}
-  	}
+	}
 
 	ut_a(buff <= buff_start + buff_len);
 
@@ -2894,7 +3049,7 @@
 					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;
@@ -2914,38 +3069,39 @@
 		use exclusive row level locks, for example, if the read is
 		done in an UPDATE statement. */
 
-	        templ_type = ROW_MYSQL_WHOLE_ROW;
+		templ_type = ROW_MYSQL_WHOLE_ROW;
 	}
 
 	if (templ_type == ROW_MYSQL_REC_FIELDS) {
-	     if (prebuilt->hint_need_to_fetch_extra_cols
-						== ROW_RETRIEVE_ALL_COLS) {
+		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 */
+			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 */
 
-			fetch_all_in_key = TRUE;
-		} else {
-			templ_type = ROW_MYSQL_WHOLE_ROW;
-		}
-	    } 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. */
+				fetch_all_in_key = TRUE;
+			} else {
+				templ_type = ROW_MYSQL_WHOLE_ROW;
+			}
+		} 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. */
 
-		fetch_primary_key_cols = TRUE;
-	    }
+			fetch_primary_key_cols = TRUE;
+		}
 	}
 
 	clust_index = dict_table_get_first_index_noninline(prebuilt->table);
@@ -3002,15 +3158,16 @@
 				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;
@@ -3026,8 +3183,8 @@
 		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);
@@ -3056,19 +3213,19 @@
 			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) {
 			templ->mysql_length_bytes = (ulint)
-				    (((Field_varstring*)field)->length_bytes);
+				(((Field_varstring*)field)->length_bytes);
 		}
 
 		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;
@@ -3086,8 +3243,9 @@
 		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);
 		}
 	}
 }
@@ -3100,22 +3258,22 @@
 ha_innobase::write_row(
 /*===================*/
 				/* out: error code */
-	mysql_byte* 	record)	/* in: a row in MySQL format */
+	mysql_byte*	record)	/* in: a row in MySQL format */
 {
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
-  	int 		error;
+	int		error;
 	longlong	auto_inc;
 	longlong	dummy;
-	ibool           auto_inc_used= FALSE;
+	ibool		auto_inc_used= FALSE;
 
-  	DBUG_ENTER("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[ht->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[ht->slot]);
 
 		fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
 		ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
@@ -3123,23 +3281,23 @@
 			"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[ht->slot]))) - 100,
 								200);
 		putc('\n', stderr);
 		ut_error;
 	}
 
-  	statistic_increment(current_thd->status_var.ha_write_count,
-			    &LOCK_status);
+	statistic_increment(current_thd->status_var.ha_write_count,
+		&LOCK_status);
 
-        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
-                table->timestamp_field->set_time();
+	if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+		table->timestamp_field->set_time();
 
 	if ((user_thd->lex->sql_command == SQLCOM_ALTER_TABLE
-	    || user_thd->lex->sql_command == SQLCOM_OPTIMIZE
-	    || user_thd->lex->sql_command == SQLCOM_CREATE_INDEX
-	    || user_thd->lex->sql_command == SQLCOM_DROP_INDEX)
-	    && num_write_row >= 10000) {
+			|| user_thd->lex->sql_command == SQLCOM_OPTIMIZE
+			|| user_thd->lex->sql_command == SQLCOM_CREATE_INDEX
+			|| user_thd->lex->sql_command == SQLCOM_DROP_INDEX)
+		&& num_write_row >= 10000) {
 		/* ALTER TABLE is COMMITted at every 10000 copied rows.
 		The IX table lock for the original table has to be re-issued.
 		As this method will be called on a temporary table where the
@@ -3177,11 +3335,11 @@
 			no need to re-acquire locks on it. */
 
 			/* Altering to InnoDB format */
-                        innobase_commit(user_thd, 1);
+			innobase_commit(ht, user_thd, 1);
 			/* Note that this transaction is still active. */
 			prebuilt->trx->active_trans = 1;
 			/* We will need an IX lock on the destination table. */
-		        prebuilt->sql_stat_start = TRUE;
+			prebuilt->sql_stat_start = TRUE;
 		} else {
 			/* Ensure that there are no other table locks than
 			LOCK_IX and LOCK_AUTO_INC on the destination table. */
@@ -3193,26 +3351,26 @@
 
 			/* Commit the transaction.  This will release the table
 			locks, so they have to be acquired again. */
-                        innobase_commit(user_thd, 1);
+			innobase_commit(ht, user_thd, 1);
 			/* Note that this transaction is still active. */
 			prebuilt->trx->active_trans = 1;
 			/* Re-acquire the table lock on the source table. */
 			row_lock_table_for_mysql(prebuilt, src_table, mode);
 			/* We will need an IX lock on the destination table. */
-		        prebuilt->sql_stat_start = TRUE;
+			prebuilt->sql_stat_start = TRUE;
 		}
 	}
 
 	num_write_row++;
 
 	if (last_query_id != user_thd->query_id) {
-	        prebuilt->sql_stat_start = TRUE;
-                last_query_id = user_thd->query_id;
+		prebuilt->sql_stat_start = TRUE;
+		last_query_id = user_thd->query_id;
 
 		innobase_release_stat_resources(prebuilt->trx);
 	}
 
-  	if (table->next_number_field && record == table->record[0]) {
+	if (table->next_number_field && record == table->record[0]) {
 		/* This is the case where the table has an
 		auto-increment column */
 
@@ -3222,7 +3380,7 @@
 		if (0 == dict_table_autoinc_peek(prebuilt->table)) {
 
 			/* This call initializes the counter */
-		        error = innobase_read_and_init_auto_inc(&dummy);
+			error = innobase_read_and_init_auto_inc(&dummy);
 
 			if (error) {
 				/* Deadlock or lock wait timeout */
@@ -3258,11 +3416,11 @@
 		}
 
 		/* We must use the handler code to update the auto-increment
-                value to be sure that we increment it correctly. */
+		value to be sure that we increment it correctly. */
 
     		if ((error= update_auto_increment()))
 			goto func_exit;
-                auto_inc_used = 1;
+		auto_inc_used = 1;
 
 	}
 
@@ -3280,34 +3438,34 @@
 
 	if (error == DB_SUCCESS && auto_inc_used) {
 
-        	/* Fetch the value that was set in the autoincrement field */
+		/* Fetch the value that was set in the autoincrement field */
 
-          	auto_inc = table->next_number_field->val_int();
+		auto_inc = table->next_number_field->val_int();
 
-          	if (auto_inc != 0) {
+		if (auto_inc != 0) {
 			/* This call will update the counter according to the
 			value that was inserted in the table */
 
-            		dict_table_autoinc_update(prebuilt->table, auto_inc);
-          	}
-        }
-
-        /* A REPLACE command and LOAD DATA INFILE REPLACE handle a duplicate
-        key error themselves, and we must update the autoinc counter if we are
-        performing those statements. */
-
-        if (error == DB_DUPLICATE_KEY && auto_inc_used
-            && (user_thd->lex->sql_command == SQLCOM_REPLACE
-                || user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT
-                || (user_thd->lex->sql_command == SQLCOM_LOAD
-                    && user_thd->lex->duplicates == DUP_REPLACE))) {
-
-                auto_inc = table->next_number_field->val_int();
-
-                if (auto_inc != 0) {
-                        dict_table_autoinc_update(prebuilt->table, auto_inc);
-                }
-        }
+			dict_table_autoinc_update(prebuilt->table, auto_inc);
+		}
+	}
+
+	/* A REPLACE command and LOAD DATA INFILE REPLACE handle a duplicate
+	key error themselves, and we must update the autoinc counter if we are
+	performing those statements. */
+
+	if (error == DB_DUPLICATE_KEY && auto_inc_used
+		&& (user_thd->lex->sql_command == SQLCOM_REPLACE
+			|| user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT
+			|| (user_thd->lex->sql_command == SQLCOM_LOAD
+				&& user_thd->lex->duplicates == DUP_REPLACE))) {
+
+		auto_inc = table->next_number_field->val_int();
+
+		if (auto_inc != 0) {
+			dict_table_autoinc_update(prebuilt->table, auto_inc);
+		}
+	}
 
 	innodb_srv_conc_exit_innodb(prebuilt->trx);
 
@@ -3318,7 +3476,7 @@
 func_exit:
 	innobase_active_small();
 
-  	DBUG_RETURN(error);
+	DBUG_RETURN(error);
 }
 
 /**************************************************************************
@@ -3330,8 +3488,8 @@
 /*================*/
 					/* out: error number or 0 */
 	upd_t*		uvect,		/* in/out: update vector */
-	mysql_byte* 	old_row,	/* in: old row in MySQL format */
-	mysql_byte* 	new_row,	/* in: new row in MySQL format */
+	mysql_byte*	old_row,	/* in: old row in MySQL format */
+	mysql_byte*	new_row,	/* in: new row in MySQL format */
 	struct st_table* table,		/* in: table in MySQL data
 					dictionary */
 	mysql_byte*	upd_buff,	/* in: buffer to use */
@@ -3347,16 +3505,18 @@
 	ulint		n_len;
 	ulint		col_pack_len;
 	byte*		new_mysql_row_col;
-	byte*	        o_ptr;
-        byte*	        n_ptr;
-        byte*	        buf;
+	byte*		o_ptr;
+	byte*		n_ptr;
+	byte*		buf;
 	upd_field_t*	ufield;
 	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;
@@ -3387,7 +3547,7 @@
 
 		field_mysql_type = field->type();
 
-		col_type = prebuilt->table->cols[i].type.mtype;
+		col_type = prebuilt->table->cols[i].mtype;
 
 		switch (col_type) {
 
@@ -3406,14 +3566,14 @@
 				1 or 2 bytes */
 
 				o_ptr = row_mysql_read_true_varchar(
-						&o_len, o_ptr,
-				    (ulint)
-				    (((Field_varstring*)field)->length_bytes));
+					&o_len, o_ptr,
+					(ulint)
+					(((Field_varstring*)field)->length_bytes));
 
 				n_ptr = row_mysql_read_true_varchar(
-						&n_len, n_ptr,
-				    (ulint)
-				    (((Field_varstring*)field)->length_bytes));
+					&n_len, n_ptr,
+					(ulint)
+					(((Field_varstring*)field)->length_bytes));
 			}
 
 			break;
@@ -3442,16 +3602,18 @@
 			/* 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(
-						&dfield,
-						(byte*)buf,
-						TRUE,
-						new_mysql_row_col,
-						col_pack_len,
-						prebuilt->table->comp);
+					&dfield,
+					(byte*)buf,
+					TRUE,
+					new_mysql_row_col,
+					col_pack_len,
+					dict_table_is_comp_noninline(
+							prebuilt->table));
 				ufield->new_val.data = dfield.data;
 				ufield->new_val.len = dfield.len;
 			} else {
@@ -3460,7 +3622,8 @@
 			}
 
 			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++;
 		}
 	}
@@ -3485,8 +3648,8 @@
 ha_innobase::update_row(
 /*====================*/
 					/* out: error number or 0 */
-	const mysql_byte* 	old_row,/* in: old row in MySQL format */
-	mysql_byte* 		new_row)/* in: new row in MySQL format */
+	const mysql_byte*	old_row,/* in: old row in MySQL format */
+	mysql_byte*		new_row)/* in: new row in MySQL format */
 {
 	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 	upd_t*		uvect;
@@ -3494,15 +3657,15 @@
 
 	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[ht->slot]);
 
-        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
-                table->timestamp_field->set_time();
+	if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
+		table->timestamp_field->set_time();
 
 	if (last_query_id != user_thd->query_id) {
-	        prebuilt->sql_stat_start = TRUE;
-                last_query_id = user_thd->query_id;
+		prebuilt->sql_stat_start = TRUE;
+		last_query_id = user_thd->query_id;
 
 		innobase_release_stat_resources(prebuilt->trx);
 	}
@@ -3555,12 +3718,12 @@
 
 	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[ht->slot]);
 
 	if (last_query_id != user_thd->query_id) {
-	        prebuilt->sql_stat_start = TRUE;
-                last_query_id = user_thd->query_id;
+		prebuilt->sql_stat_start = TRUE;
+		last_query_id = user_thd->query_id;
 
 		innobase_release_stat_resources(prebuilt->trx);
 	}
@@ -3590,8 +3753,9 @@
 }
 
 /**************************************************************************
-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)
@@ -3601,7 +3765,7 @@
 
 	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,
@@ -3617,12 +3781,55 @@
 		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[ht->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;
+	}
 }
 
 /**********************************************************************
@@ -3632,14 +3839,15 @@
 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");
+	int	error	= 0;
+	DBUG_ENTER("index_init");
 
 	error = change_active_index(keynr);
 
-  	DBUG_RETURN(error);
+	DBUG_RETURN(error);
 }
 
 /**********************************************************************
@@ -3649,10 +3857,10 @@
 ha_innobase::index_end(void)
 /*========================*/
 {
-	int 	error	= 0;
-  	DBUG_ENTER("index_end");
-        active_index=MAX_KEY;
-  	DBUG_RETURN(error);
+	int	error	= 0;
+	DBUG_ENTER("index_end");
+	active_index=MAX_KEY;
+	DBUG_RETURN(error);
 }
 
 /*************************************************************************
@@ -3665,15 +3873,15 @@
 	enum ha_rkey_function	find_flag)
 {
 	switch (find_flag) {
-  		case HA_READ_KEY_EXACT:		return(PAGE_CUR_GE);
-  			/* the above does not require the index to be UNIQUE */
-  		case HA_READ_KEY_OR_NEXT:	return(PAGE_CUR_GE);
+		case HA_READ_KEY_EXACT:		return(PAGE_CUR_GE);
+			/* the above does not require the index to be UNIQUE */
+		case HA_READ_KEY_OR_NEXT:	return(PAGE_CUR_GE);
 		case HA_READ_KEY_OR_PREV:	return(PAGE_CUR_LE);
 		case HA_READ_AFTER_KEY:		return(PAGE_CUR_G);
 		case HA_READ_BEFORE_KEY:	return(PAGE_CUR_L);
 		case HA_READ_PREFIX:		return(PAGE_CUR_GE);
-	        case HA_READ_PREFIX_LAST:       return(PAGE_CUR_LE);
-                case HA_READ_PREFIX_LAST_OR_PREV:return(PAGE_CUR_LE);
+		case HA_READ_PREFIX_LAST:	return(PAGE_CUR_LE);
+		case HA_READ_PREFIX_LAST_OR_PREV:return(PAGE_CUR_LE);
 		  /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
 		  pass a complete-field prefix of a key value as the search
 		  tuple. I.e., it is not allowed that the last field would
@@ -3754,7 +3962,7 @@
 					or error number */
 	mysql_byte*		buf,	/* in/out: buffer for the returned
 					row */
-	const mysql_byte* 	key_ptr,/* in: key value; if this is NULL
+	const mysql_byte*	key_ptr,/* in: key value; if this is NULL
 					we position the cursor at the
 					start or end of index; this can
 					also contain an InnoDB row id, in
@@ -3769,21 +3977,21 @@
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 	ulint		mode;
 	dict_index_t*	index;
-	ulint		match_mode 	= 0;
-	int 		error;
+	ulint		match_mode	= 0;
+	int		error;
 	ulint		ret;
 
-  	DBUG_ENTER("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[ht->slot]);
 
-  	statistic_increment(current_thd->status_var.ha_read_key_count,
-			    &LOCK_status);
+	statistic_increment(current_thd->status_var.ha_read_key_count,
+		&LOCK_status);
 
 	if (last_query_id != user_thd->query_id) {
-	        prebuilt->sql_stat_start = TRUE;
-                last_query_id = user_thd->query_id;
+		prebuilt->sql_stat_start = TRUE;
+		last_query_id = user_thd->query_id;
 
 		innobase_release_stat_resources(prebuilt->trx);
 	}
@@ -3791,7 +3999,7 @@
 	index = prebuilt->index;
 
 	/* Note that if the index for which the search template is built is not
-        necessarily prebuilt->index, but can also be the clustered index */
+	necessarily prebuilt->index, but can also be the clustered index */
 
 	if (prebuilt->sql_stat_start) {
 		build_template(prebuilt, user_thd, table,
@@ -3799,7 +4007,7 @@
 	}
 
 	if (key_ptr) {
-	        /* Convert the search key value to InnoDB format into
+		/* Convert the search key value to InnoDB format into
 		prebuilt->search_tuple */
 
 		row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
@@ -3812,7 +4020,7 @@
 		/* We position the cursor to the last or the first entry
 		in the index */
 
- 		dtuple_set_n_fields(prebuilt->search_tuple, 0);
+		dtuple_set_n_fields(prebuilt->search_tuple, 0);
 	}
 
 	mode = convert_search_mode_to_innobase(find_flag);
@@ -3861,15 +4069,15 @@
 int
 ha_innobase::index_read_last(
 /*=========================*/
-			           /* out: 0, HA_ERR_KEY_NOT_FOUND, or an
+				   /* out: 0, HA_ERR_KEY_NOT_FOUND, or an
 				   error code */
-        mysql_byte*       buf,     /* out: fetched row */
-        const mysql_byte* key_ptr, /* in: key value, or a prefix of a full
+	mysql_byte*	  buf,	   /* out: fetched row */
+	const mysql_byte* key_ptr, /* in: key value, or a prefix of a full
 				   key value */
-	uint              key_len) /* in: length of the key val or prefix
+	uint		  key_len) /* in: length of the key val or prefix
 				   in bytes */
 {
-        return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
+	return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
 }
 
 /************************************************************************
@@ -3879,19 +4087,19 @@
 ha_innobase::change_active_index(
 /*=============================*/
 			/* out: 0 or error code */
-	uint 	keynr)	/* in: use this index; MAX_KEY means always clustered
+	uint	keynr)	/* in: use this index; MAX_KEY means always clustered
 			index, even if it was internally generated by
 			InnoDB */
 {
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 	KEY*		key=0;
 	statistic_increment(current_thd->status_var.ha_read_key_count,
-			    &LOCK_status);
+		&LOCK_status);
 	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[ht->slot]);
 
 	active_index = keynr;
 
@@ -3899,19 +4107,20 @@
 		key = table->key_info + active_index;
 
 		prebuilt->index = dict_table_get_index_noninline(
-						     prebuilt->table,
-						     key->name);
-        } else {
+			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 "
-			       "from dict cache for table %s",
-			       keynr, key ? key->name : "NULL",
-			       prebuilt->table->name);
-	      DBUG_RETURN(1);
+		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);
 	}
 
 	assert(prebuilt->search_tuple != 0);
@@ -3943,7 +4152,7 @@
 					/* out: error number or 0 */
 	mysql_byte*	buf,		/* in/out: buffer for the returned
 					row */
-	uint 		keynr,		/* in: use this index */
+	uint		keynr,		/* in: use this index */
 	const mysql_byte* key,		/* in: key value; if this is NULL
 					we position the cursor at the
 					start or end of index */
@@ -3967,9 +4176,9 @@
 /*=======================*/
 				/* out: 0, HA_ERR_END_OF_FILE, or error
 				number */
-	mysql_byte* 	buf,	/* in/out: buffer for next row in MySQL
+	mysql_byte*	buf,	/* in/out: buffer for next row in MySQL
 				format */
-	uint 	direction,	/* in: ROW_SEL_NEXT or ROW_SEL_PREV */
+	uint	direction,	/* in: ROW_SEL_NEXT or ROW_SEL_PREV */
 	uint	match_mode)	/* in: 0, ROW_SEL_EXACT, or
 				ROW_SEL_EXACT_PREFIX */
 {
@@ -3979,8 +4188,8 @@
 
 	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[ht->slot]);
 
 	innodb_srv_conc_enter_innodb(prebuilt->trx);
 
@@ -4016,11 +4225,11 @@
 /*====================*/
 				/* out: 0, HA_ERR_END_OF_FILE, or error
 				number */
-	mysql_byte* 	buf)	/* in/out: buffer for next row in MySQL
+	mysql_byte*	buf)	/* in/out: buffer for next row in MySQL
 				format */
 {
-  	statistic_increment(current_thd->status_var.ha_read_next_count,
-			    &LOCK_status);
+	statistic_increment(current_thd->status_var.ha_read_next_count,
+		&LOCK_status);
 
 	return(general_fetch(buf, ROW_SEL_NEXT, 0));
 }
@@ -4033,12 +4242,12 @@
 /*=========================*/
 				/* out: 0, HA_ERR_END_OF_FILE, or error
 				number */
-	mysql_byte* 	buf,	/* in/out: buffer for the row */
+	mysql_byte*	buf,	/* in/out: buffer for the row */
 	const mysql_byte* key,	/* in: key value */
-	uint 		keylen)	/* in: key value length */
+	uint		keylen)	/* in: key value length */
 {
-  	statistic_increment(current_thd->status_var.ha_read_next_count,
-			    &LOCK_status);
+	statistic_increment(current_thd->status_var.ha_read_next_count,
+		&LOCK_status);
 
 	return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
 }
@@ -4052,11 +4261,11 @@
 /*====================*/
 				/* out: 0, HA_ERR_END_OF_FILE, or error
 				number */
-	mysql_byte* 	buf)	/* in/out: buffer for previous row in MySQL
+	mysql_byte*	buf)	/* in/out: buffer for previous row in MySQL
 				format */
 {
-  	statistic_increment(current_thd->status_var.ha_read_prev_count,
-			    &LOCK_status);
+	statistic_increment(current_thd->status_var.ha_read_prev_count,
+		&LOCK_status);
 
 	return(general_fetch(buf, ROW_SEL_PREV, 0));
 }
@@ -4074,19 +4283,19 @@
 {
 	int	error;
 
-  	DBUG_ENTER("index_first");
-  	statistic_increment(current_thd->status_var.ha_read_first_count,
-			    &LOCK_status);
+	DBUG_ENTER("index_first");
+	statistic_increment(current_thd->status_var.ha_read_first_count,
+		&LOCK_status);
 
-  	error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
+	error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
 
-        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
+	/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
-  	if (error == HA_ERR_KEY_NOT_FOUND) {
-  		error = HA_ERR_END_OF_FILE;
-  	}
+	if (error == HA_ERR_KEY_NOT_FOUND) {
+		error = HA_ERR_END_OF_FILE;
+	}
 
-  	DBUG_RETURN(error);
+	DBUG_RETURN(error);
 }
 
 /************************************************************************
@@ -4101,19 +4310,19 @@
 {
 	int	error;
 
-  	DBUG_ENTER("index_last");
-  	statistic_increment(current_thd->status_var.ha_read_last_count,
-			    &LOCK_status);
+	DBUG_ENTER("index_last");
+	statistic_increment(current_thd->status_var.ha_read_last_count,
+		&LOCK_status);
 
-  	error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
+	error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
 
-        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
+	/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
-  	if (error == HA_ERR_KEY_NOT_FOUND) {
-  		error = HA_ERR_END_OF_FILE;
-  	}
+	if (error == HA_ERR_KEY_NOT_FOUND) {
+		error = HA_ERR_END_OF_FILE;
+	}
 
-  	DBUG_RETURN(error);
+	DBUG_RETURN(error);
 }
 
 /********************************************************************
@@ -4138,9 +4347,16 @@
 		err = change_active_index(primary_key);
 	}
 
-  	start_of_scan = 1;
+	/* 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);
+	}
 
- 	return(err);
+	start_of_scan = 1;
+
+	return(err);
 }
 
 /*********************************************************************
@@ -4167,11 +4383,11 @@
 {
 	int	error;
 
-  	DBUG_ENTER("rnd_next");
-  	statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
-			    &LOCK_status);
+	DBUG_ENTER("rnd_next");
+	statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
+		&LOCK_status);
 
-  	if (start_of_scan) {
+	if (start_of_scan) {
 		error = index_first(buf);
 		if (error == HA_ERR_KEY_NOT_FOUND) {
 			error = HA_ERR_END_OF_FILE;
@@ -4181,7 +4397,7 @@
 		error = general_fetch(buf, ROW_SEL_NEXT, 0);
 	}
 
-  	DBUG_RETURN(error);
+	DBUG_RETURN(error);
 }
 
 /**************************************************************************
@@ -4192,7 +4408,7 @@
 /*=================*/
 				/* out: 0, HA_ERR_KEY_NOT_FOUND,
 				or error code */
-	mysql_byte* 	buf,	/* in/out: buffer for the row */
+	mysql_byte*	buf,	/* in/out: buffer for the row */
 	mysql_byte*	pos)	/* in: primary key value of the row in the
 				MySQL format, or the row id if the clustered
 				index was internally generated by InnoDB;
@@ -4206,10 +4422,10 @@
 	DBUG_DUMP("key", (char*) pos, ref_length);
 
 	statistic_increment(current_thd->status_var.ha_read_rnd_count,
-			    &LOCK_status);
+		&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[ht->slot]);
 
 	if (prebuilt->clust_index_was_generated) {
 		/* No primary key was defined for the table and we
@@ -4223,12 +4439,12 @@
 	}
 
 	if (error) {
-	        DBUG_PRINT("error", ("Got error: %d", error));
+		DBUG_PRINT("error", ("Got error: %d", error));
 		DBUG_RETURN(error);
 	}
 
 	/* Note that we assume the length of the row reference is fixed
-        for the table, and it is == ref_length */
+	for the table, and it is == ref_length */
 
 	error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
 
@@ -4238,7 +4454,7 @@
 
 	change_active_index(keynr);
 
-  	DBUG_RETURN(error);
+	DBUG_RETURN(error);
 }
 
 /*************************************************************************
@@ -4258,8 +4474,8 @@
 	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[ht->slot]);
 
 	if (prebuilt->clust_index_was_generated) {
 		/* No primary key was defined for the table and we
@@ -4302,30 +4518,30 @@
 					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;
 	ulint		n_cols;
-  	int 		error;
-  	ulint		col_type;
+	int		error;
+	ulint		col_type;
 	ulint		col_len;
-  	ulint		nulls_allowed;
+	ulint		nulls_allowed;
 	ulint		unsigned_type;
 	ulint		binary_type;
 	ulint		long_true_varchar;
 	ulint		charset_no;
-  	ulint		i;
+	ulint		i;
 
-  	DBUG_ENTER("create_table_def");
-  	DBUG_PRINT("enter", ("table_name: %s", table_name));
+	DBUG_ENTER("create_table_def");
+	DBUG_PRINT("enter", ("table_name: %s", table_name));
 
 	n_cols = form->s->fields;
 
 	/* 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 =
@@ -4380,15 +4596,14 @@
 		}
 
 		dict_mem_table_add_col(table,
-					(char*) field->field_name,
-					col_type,
-					dtype_form_prtype(
-					    (ulint)field->type()
-					     | nulls_allowed | unsigned_type
-					     | binary_type | long_true_varchar,
-					    charset_no),
-					col_len,
-					0);
+			(char*) field->field_name,
+			col_type,
+			dtype_form_prtype(
+				(ulint)field->type()
+				| nulls_allowed | unsigned_type
+				| binary_type | long_true_varchar,
+				charset_no),
+			col_len);
 	}
 
 	error = row_create_table_for_mysql(table, trx);
@@ -4412,7 +4627,7 @@
 {
 	Field*		field;
 	dict_index_t*	index;
-  	int 		error;
+	int		error;
 	ulint		n_fields;
 	KEY*		key;
 	KEY_PART_INFO*	key_part;
@@ -4420,19 +4635,19 @@
 	ulint		col_type;
 	ulint		prefix_len;
 	ulint		is_unsigned;
-  	ulint		i;
-  	ulint		j;
+	ulint		i;
+	ulint		j;
 	ulint*		field_lengths;
 
-  	DBUG_ENTER("create_index");
+	DBUG_ENTER("create_index");
 
 	key = form->key_info + key_num;
 
-    	n_fields = key->key_parts;
+	n_fields = key->key_parts;
 
-    	ind_type = 0;
+	ind_type = 0;
 
-    	if (key_num == form->s->primary_key) {
+	if (key_num == form->s->primary_key) {
 		ind_type = ind_type | DICT_CLUSTERED;
 	}
 
@@ -4478,39 +4693,36 @@
 					&is_unsigned, key_part->field);
 
 		if (DATA_BLOB == col_type
-		    || (key_part->length < field->pack_length()
-			&& field->type() != MYSQL_TYPE_VARCHAR)
-		    || (field->type() == MYSQL_TYPE_VARCHAR
-			&& key_part->length < field->pack_length()
-			          - ((Field_varstring*)field)->length_bytes)) {
+			|| (key_part->length < field->pack_length()
+				&& field->type() != MYSQL_TYPE_VARCHAR)
+			|| (field->type() == MYSQL_TYPE_VARCHAR
+				&& key_part->length < field->pack_length()
+				- ((Field_varstring*)field)->length_bytes)) {
 
-		        prefix_len = key_part->length;
+			prefix_len = key_part->length;
 
 			if (col_type == DATA_INT
-			    || col_type == DATA_FLOAT
-			    || col_type == DATA_DOUBLE
-			    || col_type == DATA_DECIMAL) {
-			  sql_print_error("MySQL is trying to create a column "
-					  "prefix index field, on an "
-					  "inappropriate data type. Table "
-					  "name %s, column name %s.",
-					  table_name,
-					  key_part->field->field_name);
+				|| col_type == DATA_FLOAT
+				|| col_type == DATA_DOUBLE
+				|| col_type == DATA_DECIMAL) {
+				sql_print_error(
+					"MySQL is trying to create a column "
+					"prefix index field, on an "
+					"inappropriate data type. Table "
+					"name %s, column name %s.",
+					table_name,
+					key_part->field->field_name);
 
-			        prefix_len = 0;
+				prefix_len = 0;
 			}
 		} else {
-		        prefix_len = 0;
+			prefix_len = 0;
 		}
 
 		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
@@ -4536,14 +4748,13 @@
 	const char*	table_name)	/* in: table name */
 {
 	dict_index_t*	index;
-  	int 		error;
+	int		error;
 
 	/* We pass 0 as the space id, and determine at a lower level the space
 	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);
@@ -4574,9 +4785,10 @@
 	char		name2[FN_REFLEN];
 	char		norm_name[FN_REFLEN];
 	THD		*thd= current_thd;
-	ib_longlong     auto_inc_value;
+	ib_longlong	auto_inc_value;
+	ulint		flags;
 
-  	DBUG_ENTER("ha_innobase::create");
+	DBUG_ENTER("ha_innobase::create");
 
 	DBUG_ASSERT(thd != NULL);
 
@@ -4584,13 +4796,13 @@
 		/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
 		but we play safe here */
 
-	        DBUG_RETURN(HA_ERR_TO_BIG_ROW);
+		DBUG_RETURN(HA_ERR_TO_BIG_ROW);
 	}
 
 	/* 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(ht, thd);
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
@@ -4616,7 +4828,7 @@
 		srv_lower_case_table_names = FALSE;
 	}
 
-	fn_format(name2, name, "", "", 2);	// Remove the .frm extension
+	strcpy(name2, name);
 
 	normalize_table_name(norm_name, name2);
 
@@ -4628,18 +4840,24 @@
 
 	/* 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) {
+	if (error) {
 		goto cleanup;
- 	}
+	}
 
 	/* 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
@@ -4656,44 +4874,33 @@
 
 		error = create_clustered_index_when_no_primary(trx,
 							norm_name);
-  		if (error) {
+		if (error) {
 			goto cleanup;
-      		}
+		}
 	}
 
 	if (primary_key_no != -1) {
 		/* In InnoDB the clustered index must always be created
 		first */
-	    	if ((error = create_index(trx, form, norm_name,
+		if ((error = create_index(trx, form, norm_name,
 					  (uint) primary_key_no))) {
 			goto cleanup;
-      		}
-      	}
+		}
+	}
 
 	for (i = 0; i < form->s->keys; i++) {
 
 		if (i != (uint) primary_key_no) {
 
-    			if ((error = create_index(trx, form, norm_name, i))) {
+			if ((error = create_index(trx, form, norm_name, i))) {
 				goto cleanup;
-      			}
-      		}
-  	}
-
-	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);
@@ -4703,7 +4910,7 @@
 		}
 	}
 
-  	innobase_commit_low(trx);
+	innobase_commit_low(trx);
 
 	row_mysql_unlock_data_dictionary(trx);
 
@@ -4713,7 +4920,7 @@
 
 	log_buffer_flush_to_disk();
 
-	innobase_table = dict_table_get(norm_name, NULL);
+	innobase_table = dict_table_get(norm_name, FALSE);
 
 	DBUG_ASSERT(innobase_table != 0);
 
@@ -4736,7 +4943,7 @@
 
 	srv_active_wake_master_thread();
 
-  	trx_free_for_mysql(trx);
+	trx_free_for_mysql(trx);
 
 	DBUG_RETURN(0);
 
@@ -4764,11 +4971,11 @@
 	trx_t*		trx;
 	int		err;
 
- 	DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
+	DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
 
 	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[ht->slot]);
 
 	dict_table = prebuilt->table;
 	trx = prebuilt->trx;
@@ -4794,7 +5001,6 @@
 {
 	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");
@@ -4807,13 +5013,13 @@
 	}
 
 	/* 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,15 +5047,15 @@
 	int	error;
 	trx_t*	parent_trx;
 	trx_t*	trx;
-	THD     *thd= current_thd;
+	THD	*thd= current_thd;
 	char	norm_name[1000];
 
- 	DBUG_ENTER("ha_innobase::delete_table");
+	DBUG_ENTER("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(ht, thd);
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
@@ -4884,7 +5090,7 @@
 
 	normalize_table_name(norm_name, name);
 
-  	/* Drop the table in InnoDB */
+	/* Drop the table in InnoDB */
 
 	error = row_drop_table_for_mysql(norm_name, trx,
 		thd->lex->sql_command == SQLCOM_DROP_DB);
@@ -4900,9 +5106,9 @@
 
 	srv_active_wake_master_thread();
 
-  	innobase_commit_low(trx);
+	innobase_commit_low(trx);
 
-  	trx_free_for_mysql(trx);
+	trx_free_for_mysql(trx);
 
 	error = convert_error_code_to_mysql(error, NULL);
 
@@ -4912,10 +5118,11 @@
 /*********************************************************************
 Removes all tables in the named database inside InnoDB. */
 
-int
+void
 innobase_drop_database(
 /*===================*/
 			/* out: error number */
+        handlerton *hton, /* in: handlerton of Innodb */
 	char*	path)	/* in: database path; inside InnoDB the name
 			of the last directory in the path is used as
 			the database name: for example, in 'mysql/data/test'
@@ -4931,7 +5138,7 @@
 	/* 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(hton, current_thd);
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
@@ -4951,7 +5158,7 @@
 	memcpy(namebuf, ptr, len);
 	namebuf[len] = '/';
 	namebuf[len + 1] = '\0';
-#ifdef  __WIN__
+#ifdef	__WIN__
 	innobase_casedn_str(namebuf);
 #endif
 	trx = trx_allocate_for_mysql();
@@ -4962,7 +5169,7 @@
 		trx->check_foreigns = FALSE;
 	}
 
-  	error = row_drop_database_for_mysql(namebuf, trx);
+	error = row_drop_database_for_mysql(namebuf, trx);
 	my_free(namebuf, MYF(0));
 
 	/* Flush the log to reduce probability that the .frm files and
@@ -4976,12 +5183,15 @@
 
 	srv_active_wake_master_thread();
 
-  	innobase_commit_low(trx);
-  	trx_free_for_mysql(trx);
-
+	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
 }
 
 /*************************************************************************
@@ -5002,12 +5212,12 @@
 	char	norm_from[1000];
 	char	norm_to[1000];
 
-  	DBUG_ENTER("ha_innobase::rename_table");
+	DBUG_ENTER("ha_innobase::rename_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(ht, current_thd);
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
@@ -5037,9 +5247,9 @@
 	normalize_table_name(norm_from, from);
 	normalize_table_name(norm_to, to);
 
-  	/* Rename the table in InnoDB */
+	/* Rename the table in InnoDB */
 
-  	error = row_rename_table_for_mysql(norm_from, norm_to, trx);
+	error = row_rename_table_for_mysql(norm_from, norm_to, trx);
 
 	/* Flush the log to reduce probability that the .frm files and
 	the InnoDB data dictionary get out-of-sync if the user runs
@@ -5052,8 +5262,8 @@
 
 	srv_active_wake_master_thread();
 
-  	innobase_commit_low(trx);
-  	trx_free_for_mysql(trx);
+	innobase_commit_low(trx);
+	trx_free_for_mysql(trx);
 
 	error = convert_error_code_to_mysql(error, NULL);
 
@@ -5068,30 +5278,33 @@
 /*==========================*/
 						/* out: estimated number of
 						rows */
-	uint 			keynr,		/* in: index number */
-        key_range		*min_key,	/* in: start key value of the
-                                                   range, may also be 0 */
+	uint			keynr,		/* in: index number */
+	key_range		*min_key,	/* in: start key value of the
+						   range, may also be 0 */
 	key_range		*max_key)	/* in: range end key val, may
-                                                   also be 0 */
+						   also be 0 */
 {
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 	KEY*		key;
 	dict_index_t*	index;
-	mysql_byte*	key_val_buff2 	= (mysql_byte*) my_malloc(
+	mysql_byte*	key_val_buff2	= (mysql_byte*) my_malloc(
 						  table->s->reclength
-      					+ table->s->max_key_length + 100,
+					+ table->s->max_key_length + 100,
 								MYF(MY_FAE));
 	ulint		buff2_len = table->s->reclength
-      					+ table->s->max_key_length + 100;
+					+ table->s->max_key_length + 100;
 	dtuple_t*	range_start;
 	dtuple_t*	range_end;
 	ib_longlong	n_rows;
 	ulint		mode1;
 	ulint		mode2;
-	void*           heap1;
-	void*           heap2;
+	void*		heap1;
+	void*		heap2;
 
-   	DBUG_ENTER("records_in_range");
+	DBUG_ENTER("records_in_range");
+
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[ht->slot]);
 
 	prebuilt->trx->op_info = (char*)"estimating records in index range";
 
@@ -5107,17 +5320,17 @@
 	index = dict_table_get_index_noninline(prebuilt->table, key->name);
 
 	range_start = dtuple_create_for_mysql(&heap1, key->key_parts);
- 	dict_index_copy_types(range_start, index, key->key_parts);
+	dict_index_copy_types(range_start, index, key->key_parts);
 
 	range_end = dtuple_create_for_mysql(&heap2, key->key_parts);
- 	dict_index_copy_types(range_end, index, key->key_parts);
+	dict_index_copy_types(range_end, index, key->key_parts);
 
 	row_sel_convert_mysql_key_to_innobase(
 				range_start, (byte*) key_val_buff,
 				(ulint)upd_and_key_val_buff_len,
 				index,
 				(byte*) (min_key ? min_key->key :
-                                         (const mysql_byte*) 0),
+					 (const mysql_byte*) 0),
 				(ulint) (min_key ? min_key->length : 0),
 				prebuilt->trx);
 
@@ -5125,21 +5338,21 @@
 				range_end, (byte*) key_val_buff2,
 				buff2_len, index,
 				(byte*) (max_key ? max_key->key :
-                                         (const mysql_byte*) 0),
+					 (const mysql_byte*) 0),
 				(ulint) (max_key ? max_key->length : 0),
 				prebuilt->trx);
 
 	mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
-                                                HA_READ_KEY_EXACT);
+						HA_READ_KEY_EXACT);
 	mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
-                                                HA_READ_KEY_EXACT);
+						HA_READ_KEY_EXACT);
 
 	n_rows = btr_estimate_n_rows_in_range(index, range_start,
 						mode1, range_end, mode2);
 	dtuple_free_for_mysql(heap1);
 	dtuple_free_for_mysql(heap2);
 
-    	my_free((gptr) key_val_buff2, MYF(0));
+	my_free((gptr) key_val_buff2, MYF(0));
 
 	prebuilt->trx->op_info = (char*)"";
 
@@ -5150,7 +5363,7 @@
 	Add 1 to the value to make sure MySQL does not make the assumption! */
 
 	if (n_rows == 0) {
-	        n_rows = 1;
+		n_rows = 1;
 	}
 
 	DBUG_RETURN((ha_rows) n_rows);
@@ -5170,7 +5383,7 @@
 	ulonglong	estimate;
 	ulonglong	local_data_file_length;
 
- 	DBUG_ENTER("estimate_rows_upper_bound");
+	DBUG_ENTER("estimate_rows_upper_bound");
 
 	/* We do not know if MySQL can call this function before calling
 	external_lock(). To be safe, update the thd of the current table
@@ -5179,7 +5392,7 @@
 	update_thd(current_thd);
 
 	prebuilt->trx->op_info = (char*)
-	                         "calculating upper bound for table rows";
+				 "calculating upper bound for table rows";
 
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
@@ -5189,7 +5402,7 @@
 	index = dict_table_get_first_index_noninline(prebuilt->table);
 
 	local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
-    							* UNIV_PAGE_SIZE;
+							* UNIV_PAGE_SIZE;
 
 	/* Calculate a minimum length for a clustered index record and from
 	that an upper bound for the number of rows. Since we only calculate
@@ -5232,16 +5445,16 @@
 ha_innobase::read_time(
 /*===================*/
 			/* out: estimated time measured in disk seeks */
-	uint    index,	/* in: key number */
+	uint	index,	/* in: key number */
 	uint	ranges,	/* in: how many ranges */
 	ha_rows rows)	/* in: estimated number of rows in the ranges */
 {
 	ha_rows total_rows;
-	double  time_for_scan;
+	double	time_for_scan;
 
 	if (index != table->s->primary_key) {
 		/* Not clustered */
-	  	return(handler::read_time(index, ranges, rows));
+		return(handler::read_time(index, ranges, rows));
 	}
 
 	if (rows <= 2) {
@@ -5256,7 +5469,7 @@
 
 	if ((total_rows = estimate_rows_upper_bound()) < rows) {
 
-	  	return(time_for_scan);
+		return(time_for_scan);
 	}
 
 	return(ranges + (double) rows / (double) total_rows * time_for_scan);
@@ -5279,18 +5492,18 @@
 	ulong		j;
 	ulong		i;
 	char		path[FN_REFLEN];
-	os_file_stat_t  stat_info;
+	os_file_stat_t	stat_info;
 
- 	DBUG_ENTER("info");
+	DBUG_ENTER("info");
 
-        /* If we are forcing recovery at a high level, we will suppress
+	/* If we are forcing recovery at a high level, we will suppress
 	statistics calculation on tables, because that may crash the
 	server if an index is badly corrupted. */
 
-        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
                 DBUG_RETURN(HA_ERR_CRASHED);
-        }
+	}
 
 	/* We do not know if MySQL can call this function before calling
 	external_lock(). To be safe, update the thd of the current table
@@ -5305,21 +5518,21 @@
 
 	trx_search_latch_release_if_reserved(prebuilt->trx);
 
- 	ib_table = prebuilt->table;
+	ib_table = prebuilt->table;
 
- 	if (flag & HA_STATUS_TIME) {
- 		/* In sql_show we call with this flag: update then statistics
- 		so that they are up-to-date */
+	if (flag & HA_STATUS_TIME) {
+		/* In sql_show we call with this flag: update then statistics
+		so that they are up-to-date */
 
-	        prebuilt->trx->op_info = (char*)"updating table statistics";
+		prebuilt->trx->op_info = (char*)"updating table statistics";
 
- 		dict_update_statistics(ib_table);
+		dict_update_statistics(ib_table);
 
 		prebuilt->trx->op_info = (char*)
-		                          "returning various info to MySQL";
+					  "returning various info to MySQL";
+
 		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,9 +5540,9 @@
 		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;
 		}
- 	}
+	}
 
 	if (flag & HA_STATUS_VARIABLE) {
 		n_rows = ib_table->stat_n_rows;
@@ -5355,23 +5568,23 @@
 			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)
+					* UNIV_PAGE_SIZE;
+		stats.index_file_length = ((ulonglong)
 				ib_table->stat_sum_of_other_index_sizes)
-    					* UNIV_PAGE_SIZE;
-    		delete_length = 0;
-    		check_time = 0;
-
-    		if (records == 0) {
-    			mean_rec_length = 0;
-    		} else {
-    			mean_rec_length = (ulong) (data_file_length / records);
-    		}
-    	}
+					* UNIV_PAGE_SIZE;
+		stats.delete_length = 0;
+		stats.check_time = 0;
+
+		if (stats.records == 0) {
+			stats.mean_rec_length = 0;
+		} else {
+			stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
+		}
+	}
 
 	if (flag & HA_STATUS_CONST) {
 		index = dict_table_get_first_index_noninline(ib_table);
@@ -5389,7 +5602,7 @@
 						".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;
@@ -5398,25 +5611,25 @@
 			for (j = 0; j < table->key_info[i].key_parts; j++) {
 
 				if (j + 1 > index->n_uniq) {
-				        ut_print_timestamp(stderr);
+					ut_print_timestamp(stderr);
 					sql_print_error(
 "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)
 							index->n_uniq, j + 1);
-				        break;
+					break;
 				}
 
 				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 /
-   				         index->stat_n_diff_key_vals[j + 1]);
+					rec_per_key = (ha_rows)(stats.records /
+					 index->stat_n_diff_key_vals[j + 1]);
 				}
 
 				/* Since MySQL seems to favor table scans
@@ -5430,7 +5643,7 @@
 					rec_per_key = 1;
 				}
 
- 				table->key_info[i].rec_per_key[j]=
+				table->key_info[i].rec_per_key[j]=
 				  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
 				  rec_per_key;
 			}
@@ -5439,13 +5652,12 @@
 		}
 	}
 
-  	if (flag & HA_STATUS_ERRKEY) {
+	if (flag & HA_STATUS_ERRKEY) {
 		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) {
 		longlong	auto_inc;
@@ -5471,7 +5683,7 @@
 			}
 		}
 
-		auto_increment_value = auto_inc;
+		stats.auto_increment_value = auto_inc;
 	}
 
 	prebuilt->trx->op_info = (char*)"";
@@ -5497,7 +5709,7 @@
 }
 
 /**************************************************************************
-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
@@ -5506,7 +5718,7 @@
 	THD*		thd,		/* in: connection thread handle */
 	HA_CHECK_OPT*	check_opt)	/* in: currently ignored */
 {
-        return(HA_ADMIN_TRY_ALTER);
+	return(HA_ADMIN_TRY_ALTER);
 }
 
 /***********************************************************************
@@ -5519,8 +5731,8 @@
 /*===============*/
 					/* out: HA_ADMIN_CORRUPT or
 					HA_ADMIN_OK */
-	THD* 		thd,		/* in: user thread handle */
-	HA_CHECK_OPT* 	check_opt)	/* in: check options, currently
+	THD*		thd,		/* in: user thread handle */
+	HA_CHECK_OPT*	check_opt)	/* in: check options, currently
 					ignored */
 {
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
@@ -5528,7 +5740,7 @@
 
 	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[ht->slot]);
 
 	if (prebuilt->mysql_template == NULL) {
 		/* Build the template; we will use a dummy template
@@ -5543,7 +5755,7 @@
 		return(HA_ADMIN_OK);
 	}
 
-  	return(HA_ADMIN_CORRUPT);
+	return(HA_ADMIN_CORRUPT);
 }
 
 /*****************************************************************
@@ -5556,7 +5768,7 @@
 /*==============================*/
 				/* out: table comment + InnoDB free space +
 				info on foreign keys */
-        const char*	comment)/* in: table comment defined by user */
+	const char*	comment)/* in: table comment defined by user */
 {
 	uint	length			= (uint) strlen(comment);
 	char*				str;
@@ -5587,8 +5799,8 @@
 	rewind(srv_dict_tmpfile);
 
 	fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB",
-      		   (ulong) fsp_get_available_space_in_free_extents(
-      					prebuilt->table->space));
+		   (ulong) fsp_get_available_space_in_free_extents(
+					prebuilt->table->space));
 
 	dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 				prebuilt->trx, prebuilt->table);
@@ -5618,9 +5830,9 @@
 
 	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
 
-        prebuilt->trx->op_info = (char*)"";
+	prebuilt->trx->op_info = (char*)"";
 
-  	return(str ? str : (char*) comment);
+	return(str ? str : (char*) comment);
 }
 
 /***********************************************************************
@@ -5681,7 +5893,7 @@
 
 	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
 
-  	return(str);
+	return(str);
 }
 
 
@@ -5699,85 +5911,119 @@
   mutex_enter_noninline(&(dict_sys->mutex));
   foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
-  while (foreign != NULL)
-  {
-    uint i;
-    FOREIGN_KEY_INFO f_key_info;
-    LEX_STRING *name= 0;
-    const char *tmp_buff;
-
-    tmp_buff= foreign->id;
-    i= 0;
-    while (tmp_buff[i] != '/')
-      i++;
-    tmp_buff+= i + 1;
-    f_key_info.forein_id= make_lex_string(thd, 0, tmp_buff,
-                                          (uint) strlen(tmp_buff), 1);
-    tmp_buff= foreign->referenced_table_name;
-    i= 0;
-    while (tmp_buff[i] != '/')
-      i++;
-    f_key_info.referenced_db= make_lex_string(thd, 0,
-                                              tmp_buff, i, 1);
-    tmp_buff+= i + 1;
-    f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff,
-                                               (uint) strlen(tmp_buff), 1);
-
-    for (i= 0;;)
-    {
-      tmp_buff= foreign->foreign_col_names[i];
-      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);
-      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)
-    {
-      length=17;
-      tmp_buff= "ON DELETE CASCADE";
-    }
-    else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL)
-    {
-      length=18;
-      tmp_buff= "ON DELETE SET NULL";
-    }
-    else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION)
-    {
-      length=19;
-      tmp_buff= "ON DELETE NO ACTION";
-    }
-    else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE)
-    {
-      length=17;
-      tmp_buff= "ON UPDATE CASCADE";
-    }
-    else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL)
-    {
-      length=18;
-      tmp_buff= "ON UPDATE SET NULL";
-    }
-    else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION)
-    {
-      length=19;
-      tmp_buff= "ON UPDATE NO ACTION";
-    }
-    f_key_info.constraint_method= make_lex_string(thd,
-                                                  f_key_info.constraint_method,
-                                                  tmp_buff, length, 1);
-
-    FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
-                                    thd->memdup((gptr) &f_key_info,
-                                                sizeof(FOREIGN_KEY_INFO)));
-    f_key_list->push_back(pf_key_info);
-    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+  while (foreign != NULL) {
+	  uint i;
+	  FOREIGN_KEY_INFO f_key_info;
+	  LEX_STRING *name= 0;
+          uint ulen;
+          char uname[NAME_LEN*3+1];           /* Unencoded name */
+          char db_name[NAME_LEN*3+1];
+	  const char *tmp_buff;
+
+	  tmp_buff= foreign->id;
+	  i= 0;
+	  while (tmp_buff[i] != '/')
+		  i++;
+	  tmp_buff+= i + 1;
+	  f_key_info.forein_id= make_lex_string(thd, 0, tmp_buff,
+		  (uint) strlen(tmp_buff), 1);
+	  tmp_buff= foreign->referenced_table_name;
+
+          /* Database name */
+	  i= 0;
+	  while (tmp_buff[i] != '/')
+          {
+            db_name[i]= tmp_buff[i];
+            i++;
+          }
+          db_name[i]= 0;
+          ulen= filename_to_tablename(db_name, uname, sizeof(uname));
+          f_key_info.referenced_db= make_lex_string(thd, 0, uname, ulen, 1);
+
+          /* Table name */
+	  tmp_buff+= i + 1;
+          ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
+          f_key_info.referenced_table= make_lex_string(thd, 0, uname,
+                                                       ulen, 1);
+
+	  for (i= 0;;) {
+		  tmp_buff= foreign->foreign_col_names[i];
+		  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);
+		  f_key_info.referenced_fields.push_back(name);
+		  if (++i >= foreign->n_fields)
+			  break;
+	  }
+
+          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=9;
+            tmp_buff= "NO ACTION";
+          }
+          else
+          {
+            length=8;
+            tmp_buff= "RESTRICT";
+          }
+          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=7;
+            tmp_buff= "CASCADE";
+          }
+          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
+          {
+            length=8;
+            tmp_buff= "SET NULL";
+          }
+          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
+          {
+            length=9;
+            tmp_buff= "NO ACTION";
+          }
+          else
+          {
+            length=8;
+            tmp_buff= "RESTRICT";
+          }
+          f_key_info.update_method= make_lex_string(thd, f_key_info.update_method,
+                                                    tmp_buff, length, 1);
+          if (foreign->referenced_index &&
+              foreign->referenced_index->name)
+          {
+            f_key_info.referenced_key_name= 
+              make_lex_string(thd, f_key_info.referenced_key_name,
+                              foreign->referenced_index->name,
+                              strlen(foreign->referenced_index->name), 1);
+          }
+
+	  FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
+		  thd->memdup((gptr) &f_key_info,
+			  sizeof(FOREIGN_KEY_INFO)));
+	  f_key_list->push_back(pf_key_info);
+	  foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
   }
   mutex_exit_noninline(&(dict_sys->mutex));
   prebuilt->trx->op_info = (char*)"";
+
   DBUG_RETURN(0);
 }
 
@@ -5793,7 +6039,11 @@
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 	bool	can_switch;
 
- 	DBUG_ENTER("ha_innobase::can_switch_engines");
+	DBUG_ENTER("ha_innobase::can_switch_engines");
+
+	ut_a(prebuilt->trx ==
+		(trx_t*) current_thd->ha_data[ht->slot]);
+
 	prebuilt->trx->op_info =
 			"determining if there are foreign key constraints";
 	row_mysql_lock_data_dictionary(prebuilt->trx);
@@ -5835,7 +6085,7 @@
 void
 ha_innobase::free_foreign_key_create_info(
 /*======================================*/
-	char*	str)	/* in, own: create info string to free  */
+	char*	str)	/* in, own: create info string to free	*/
 {
 	if (str) {
 		my_free(str, MYF(0));
@@ -5850,8 +6100,7 @@
 /*===============*/
 			   /* 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;
 
@@ -5860,38 +6109,21 @@
 	obsolete! */
 
 	switch (operation) {
-                case HA_EXTRA_FLUSH:
-                        if (prebuilt->blob_heap) {
-                                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;
-    	        	break;
+		case HA_EXTRA_FLUSH:
+			if (prebuilt->blob_heap) {
+				row_mysql_prebuilt_free_blob_heap(prebuilt);
+			}
+			break;
+		case HA_EXTRA_RESET_STATE:
+			prebuilt->keep_other_fields_on_keyread = 0;
+			prebuilt->read_just_key = 0;
+			break;
 		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;
+			prebuilt->read_just_key = 0;
 			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;
-			}
+		case HA_EXTRA_KEYREAD:
+			prebuilt->read_just_key = 1;
 			break;
-	        case HA_EXTRA_KEYREAD:
-	        	prebuilt->read_just_key = 1;
-	        	break;
 		case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
 			prebuilt->keep_other_fields_on_keyread = 1;
 			break;
@@ -5902,6 +6134,18 @@
 	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
@@ -5917,9 +6161,9 @@
 int
 ha_innobase::start_stmt(
 /*====================*/
-	              /* out: 0 or error code */
-	THD*    thd,  /* in: handle to the user thread */
-        thr_lock_type lock_type)
+				/* out: 0 or error code */
+	THD*		thd,	/* in: handle to the user thread */
+	thr_lock_type	lock_type)
 {
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 	trx_t*		trx;
@@ -5940,19 +6184,19 @@
 	prebuilt->sql_stat_start = TRUE;
 	prebuilt->hint_need_to_fetch_extra_cols = 0;
 	prebuilt->read_just_key = 0;
-        prebuilt->keep_other_fields_on_keyread = FALSE;
+	prebuilt->keep_other_fields_on_keyread = FALSE;
 
 	if (!prebuilt->mysql_has_locked) {
-	        /* This handle is for a temporary table created inside
-	        this same LOCK TABLES; since MySQL does NOT call external_lock
-	        in this case, we must use x-row locks inside InnoDB to be
-	        prepared for an update of a row */
+		/* This handle is for a temporary table created inside
+		this same LOCK TABLES; since MySQL does NOT call external_lock
+		in this case, we must use x-row locks inside InnoDB to be
+		prepared for an update of a row */
 
-	        prebuilt->select_lock_type = LOCK_X;
+		prebuilt->select_lock_type = LOCK_X;
 	} else {
 		if (trx->isolation_level != TRX_ISO_SERIALIZABLE
-		    && thd->lex->sql_command == SQLCOM_SELECT
-		    && lock_type == TL_READ) {
+			&& thd->lex->sql_command == SQLCOM_SELECT
+			&& lock_type == TL_READ) {
 
 			/* For other than temporary tables, we obtain
 			no lock for consistent read (plain SELECT). */
@@ -5965,7 +6209,7 @@
 			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;
@@ -5975,12 +6219,12 @@
 	trx->detailed_error[0] = '\0';
 
 	/* Set the MySQL flag to mark that there is an active transaction */
-        if (trx->active_trans == 0) {
+	if (trx->active_trans == 0) {
 
-                innobase_register_trx_and_stmt(thd);
-                trx->active_trans = 1;
-        } else {
-		innobase_register_stmt(thd);
+		innobase_register_trx_and_stmt(ht, thd);
+		trx->active_trans = 1;
+	} else {
+		innobase_register_stmt(ht, thd);
 	}
 
 	return(0);
@@ -6016,14 +6260,14 @@
 int
 ha_innobase::external_lock(
 /*=======================*/
-			        /* out: 0 */
+				/* out: 0 */
 	THD*	thd,		/* in: handle to the user thread */
-	int 	lock_type)	/* in: lock type */
+	int	lock_type)	/* in: lock type */
 {
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 	trx_t*		trx;
 
-  	DBUG_ENTER("ha_innobase::external_lock");
+	DBUG_ENTER("ha_innobase::external_lock");
 	DBUG_PRINT("enter",("lock_type: %d", lock_type));
 
 	update_thd(thd);
@@ -6051,26 +6295,20 @@
 
 		/* Set the MySQL flag to mark that there is an active
 		transaction */
-                if (trx->active_trans == 0) {
+		if (trx->active_trans == 0) {
 
-                        innobase_register_trx_and_stmt(thd);
-                        trx->active_trans = 1;
-                } else if (trx->n_mysql_tables_in_use == 0) {
-			innobase_register_stmt(thd);
+			innobase_register_trx_and_stmt(ht, thd);
+			trx->active_trans = 1;
+		} else if (trx->n_mysql_tables_in_use == 0) {
+			innobase_register_stmt(ht, thd);
 		}
 
 		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
+			&& prebuilt->select_lock_type == LOCK_NONE
+			&& (thd->options
 				& (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
 			/* To get serializable execution, we let InnoDB
@@ -6099,13 +6337,12 @@
 		if (prebuilt->select_lock_type != LOCK_NONE) {
 
 			if (thd->in_lock_tables &&
-			    thd->lex->sql_command == SQLCOM_LOCK_TABLES &&
-			    thd->variables.innodb_table_locks &&
-			    (thd->options & OPTION_NOT_AUTOCOMMIT)) {
-
-				ulint	error;
-				error = row_lock_table_for_mysql(prebuilt,
-							NULL, 0);
+				thd->lex->sql_command == SQLCOM_LOCK_TABLES &&
+				thd->variables.innodb_table_locks &&
+				(thd->options & OPTION_NOT_AUTOCOMMIT)) {
+
+				ulint	error = row_lock_table_for_mysql(
+					prebuilt, NULL, 0);
 
 				if (error != DB_SUCCESS) {
 					error = convert_error_code_to_mysql(
@@ -6114,7 +6351,7 @@
 				}
 			}
 
-		  	trx->mysql_n_tables_locked++;
+			trx->mysql_n_tables_locked++;
 		}
 
 		DBUG_RETURN(0);
@@ -6130,7 +6367,7 @@
 
 	if (trx->n_mysql_tables_in_use == 0) {
 
-	        trx->mysql_n_tables_locked = 0;
+		trx->mysql_n_tables_locked = 0;
 		prebuilt->used_in_HANDLER = FALSE;
 
 		/* Release a possible FIFO ticket and search latch. Since we
@@ -6140,12 +6377,12 @@
 		innobase_release_stat_resources(trx);
 
 		if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
-                        if (trx->active_trans != 0) {
-                                innobase_commit(thd, TRUE);
+			if (trx->active_trans != 0) {
+				innobase_commit(ht, thd, TRUE);
 			}
 		} else {
 			if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
-	    					&& trx->global_read_view) {
+						&& trx->global_read_view) {
 
 				/* At low transaction isolation levels we let
 				each consistent read set its own snapshot */
@@ -6165,14 +6402,14 @@
 int
 ha_innobase::transactional_table_lock(
 /*==================================*/
-			        /* out: error code */
+				/* out: error code */
 	THD*	thd,		/* in: handle to the user thread */
-	int 	lock_type)	/* in: lock type */
+	int	lock_type)	/* in: lock type */
 {
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 	trx_t*		trx;
 
-  	DBUG_ENTER("ha_innobase::transactional_table_lock");
+	DBUG_ENTER("ha_innobase::transactional_table_lock");
 	DBUG_PRINT("enter",("lock_type: %d", lock_type));
 
 	/* We do not know if MySQL can call this function before calling
@@ -6181,14 +6418,14 @@
 
 	update_thd(thd);
 
- 	if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
-	        ut_print_timestamp(stderr);
-	        fprintf(stderr, "  InnoDB error:\n"
+	if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
+		ut_print_timestamp(stderr);
+		fprintf(stderr, "  InnoDB error:\n"
 "MySQL is trying to use a table handle but the .ibd file for\n"
 "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);
@@ -6209,8 +6446,8 @@
 		prebuilt->select_lock_type = LOCK_S;
 		prebuilt->stored_select_lock_type = LOCK_S;
 	} else {
-	        ut_print_timestamp(stderr);
-	        fprintf(stderr, "  InnoDB error:\n"
+		ut_print_timestamp(stderr);
+		fprintf(stderr, "  InnoDB error:\n"
 "MySQL is trying to set transactional table lock with corrupted lock type\n"
 "to table %s, lock type %d does not exist.\n",
 				prebuilt->table->name, lock_type);
@@ -6220,11 +6457,11 @@
 	/* MySQL is setting a new transactional table lock */
 
 	/* Set the MySQL flag to mark that there is an active transaction */
-        if (trx->active_trans == 0) {
+	if (trx->active_trans == 0) {
 
-                innobase_register_trx_and_stmt(thd);
-                trx->active_trans = 1;
-        }
+		innobase_register_trx_and_stmt(ht, thd);
+		trx->active_trans = 1;
+	}
 
 	if (thd->in_lock_tables && thd->variables.innodb_table_locks) {
 		ulint	error = DB_SUCCESS;
@@ -6252,11 +6489,15 @@
 /****************************************************************************
 Here we export InnoDB status variables to MySQL.  */
 
-void
-innodb_export_status(void)
-/*======================*/
+int
+innodb_export_status()
+/*==================*/
 {
-  srv_export_innodb_status();
+	if (innodb_inited) {
+		srv_export_innodb_status();
+	}
+
+	return 0;
 }
 
 /****************************************************************************
@@ -6266,25 +6507,23 @@
 bool
 innodb_show_status(
 /*===============*/
-	THD*	thd)	/* in: the MySQL query thread of the caller */
+	handlerton*	hton,	/* in: the innodb handlerton */
+	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;
 	ulint			trx_list_start = ULINT_UNDEFINED;
 	ulint			trx_list_end = ULINT_UNDEFINED;
 
-        DBUG_ENTER("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);
-        }
+	if (have_innodb != SHOW_OPTION_YES) {
+		DBUG_RETURN(FALSE);
+	}
 
-	trx = check_trx_exists(thd);
+	trx = check_trx_exists(hton, thd);
 
 	innobase_release_stat_resources(trx);
 
@@ -6314,11 +6553,10 @@
 	/* allocate buffer for the string, and
 	read the contents of the temporary file */
 
-	if (!(str = my_malloc(usable_len + 1, MYF(0))))
-        {
-          mutex_exit_noninline(&srv_monitor_file_mutex);
-          DBUG_RETURN(TRUE);
-        }
+	if (!(str = my_malloc(usable_len + 1, MYF(0)))) {
+	  mutex_exit_noninline(&srv_monitor_file_mutex);
+	  DBUG_RETURN(TRUE);
+	}
 
 	rewind(srv_monitor_file);
 	if (flen < MAX_STATUS_SIZE) {
@@ -6343,28 +6581,15 @@
 
 	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;
 	}
+	my_free(str, MYF(0));
 
-        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);
+	DBUG_RETURN(FALSE);
 }
 
 /****************************************************************************
@@ -6372,130 +6597,131 @@
 
 bool
 innodb_mutex_show_status(
-/*===============*/
-  THD*  thd)  /* in: the MySQL query thread of the caller */
+/*=====================*/
+	handlerton*	hton,	/* in: the innodb handlerton */
+	THD*		thd,		/* in: the MySQL query thread of the
+					caller */
+	stat_print_fn*	stat_print)
 {
-  Protocol        *protocol= thd->protocol;
-  List<Item> field_list;
-  mutex_t*  mutex;
+	char buf1[IO_SIZE], buf2[IO_SIZE];
+	mutex_t*  mutex;
 #ifdef UNIV_DEBUG
-  ulint   rw_lock_count= 0;
-  ulint   rw_lock_count_spin_loop= 0;
-  ulint   rw_lock_count_spin_rounds= 0;
-  ulint   rw_lock_count_os_wait= 0;
-  ulint   rw_lock_count_os_yield= 0;
-  ulonglong rw_lock_wait_time= 0;
+	ulint	  rw_lock_count= 0;
+	ulint	  rw_lock_count_spin_loop= 0;
+	ulint	  rw_lock_count_spin_rounds= 0;
+	ulint	  rw_lock_count_os_wait= 0;
+	ulint	  rw_lock_count_os_yield= 0;
+	ulonglong rw_lock_wait_time= 0;
 #endif /* UNIV_DEBUG */
-  DBUG_ENTER("innodb_mutex_show_status");
+	uint	  hton_name_len= strlen(innobase_hton_name), buf1len, buf2len;
+	DBUG_ENTER("innodb_mutex_show_status");
 
-#ifdef UNIV_DEBUG
-  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));
-#else /* UNIV_DEBUG */
-  field_list.push_back(new Item_empty_string("File", FN_REFLEN));
-  field_list.push_back(new Item_uint("Line", 21));
-  field_list.push_back(new Item_uint("OS_waits", 21));
-#endif /* UNIV_DEBUG */
+	mutex_enter_noninline(&mutex_list_mutex);
 
-  if (protocol->send_fields(&field_list,
-                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
-    DBUG_RETURN(TRUE);
+	mutex = UT_LIST_GET_FIRST(mutex_list);
 
-  mutex_enter_noninline(&mutex_list_mutex);
-
-  mutex = UT_LIST_GET_FIRST(mutex_list);
-
-  while ( mutex != NULL )
-  {
+	while (mutex != NULL) {
 #ifdef UNIV_DEBUG
-    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())
-        {
-          mutex_exit_noninline(&mutex_list_mutex);
-          DBUG_RETURN(1);
-        }
-      }
-    }
-    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;
-      rw_lock_count_os_wait += mutex->count_os_wait;
-      rw_lock_count_os_yield += mutex->count_os_yield;
-      rw_lock_wait_time += mutex->lspent_time;
-    }
+		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,
+					(ulong) (mutex->lspent_time/1000));
+
+				if (stat_print(thd, innobase_hton_name,
+						hton_name_len, buf1, buf1len,
+						buf2, buf2len)) {
+					mutex_exit_noninline(
+						&mutex_list_mutex);
+					DBUG_RETURN(1);
+				}
+			}
+		}
+		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;
+			rw_lock_count_os_wait += mutex->count_os_wait;
+			rw_lock_count_os_yield += mutex->count_os_yield;
+			rw_lock_wait_time += mutex->lspent_time;
+		}
 #else /* UNIV_DEBUG */
-    protocol->prepare_for_resend();
-    protocol->store(mutex->cfile_name, system_charset_info);
-    protocol->store((ulonglong)mutex->cline);
-    protocol->store((ulonglong)mutex->count_os_wait);
-
-    if (protocol->write())
-    {
-      mutex_exit_noninline(&mutex_list_mutex);
-      DBUG_RETURN(1);
-    }
+		buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%lu",
+				     mutex->cfile_name, (ulong) mutex->cline);
+		buf2len= my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
+				     mutex->count_os_wait);
+
+		if (stat_print(thd, innobase_hton_name,
+			       hton_name_len, buf1, buf1len,
+			       buf2, buf2len)) {
+			mutex_exit_noninline(&mutex_list_mutex);
+			DBUG_RETURN(1);
+		}
 #endif /* UNIV_DEBUG */
 
-    mutex = UT_LIST_GET_NEXT(list, mutex);
-  }
+		mutex = UT_LIST_GET_NEXT(list, mutex);
+	}
 
-  mutex_exit_noninline(&mutex_list_mutex);
+	mutex_exit_noninline(&mutex_list_mutex);
 
 #ifdef UNIV_DEBUG
-  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);
-
-  if (protocol->write())
-  {
-    DBUG_RETURN(1);
-  }
+	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,
+		(ulong) (rw_lock_wait_time/1000));
+
+	if (stat_print(thd, innobase_hton_name, hton_name_len,
+			STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
+		DBUG_RETURN(1);
+	}
 #endif /* UNIV_DEBUG */
 
-  send_eof(thd);
-  DBUG_RETURN(FALSE);
+	DBUG_RETURN(FALSE);
+}
+
+bool innobase_show_status(handlerton *hton, THD* thd, 
+                          stat_print_fn* stat_print,
+                          enum ha_stat_type stat_type)
+{
+	switch (stat_type) {
+	case HA_ENGINE_STATUS:
+		return innodb_show_status(hton, thd, stat_print);
+	case HA_ENGINE_MUTEX:
+		return innodb_mutex_show_status(hton, thd, stat_print);
+	default:
+		return FALSE;
+	}
 }
 
+
 /****************************************************************************
  Handling the shared INNOBASE_SHARE structure that is needed to provide table
  locking.
 ****************************************************************************/
 
-static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
-			      my_bool not_used __attribute__((unused)))
+static mysql_byte* innobase_get_key(INNOBASE_SHARE* share, uint* length,
+	my_bool not_used __attribute__((unused)))
 {
-  *length=share->table_name_length;
-  return (mysql_byte*) share->table_name;
+	*length=share->table_name_length;
+
+	return (mysql_byte*) share->table_name;
 }
 
-static INNOBASE_SHARE *get_share(const char *table_name)
+static INNOBASE_SHARE* get_share(const char* table_name)
 {
 	INNOBASE_SHARE *share;
 	pthread_mutex_lock(&innobase_share_mutex);
@@ -6530,17 +6756,18 @@
 	return share;
 }
 
-static void free_share(INNOBASE_SHARE *share)
+static void free_share(INNOBASE_SHARE* share)
 {
-  pthread_mutex_lock(&innobase_share_mutex);
-  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);
+	pthread_mutex_lock(&innobase_share_mutex);
+
+	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);
 }
 
 /*********************************************************************
@@ -6563,22 +6790,45 @@
 						pointer to the 'lock' field
 						of current handle is stored
 						next to this array */
-	enum thr_lock_type 	lock_type)	/* in: lock type to store in
+	enum thr_lock_type	lock_type)	/* in: lock type to store in
 						'lock'; this may also be
 						TL_IGNORE */
 {
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
+	trx_t*		trx;
 
-	/* NOTE: MySQL  can call this function with lock 'type' TL_IGNORE!
+	/* 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(ht, 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) ||
-	    (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
-	    lock_type == TL_READ_WITH_SHARED_LOCKS ||
-	    lock_type == TL_READ_NO_INSERT ||
-	    (thd->lex->sql_command != SQLCOM_SELECT
-	     && lock_type != TL_IGNORE)) {
+	/* 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 ||
+		(thd->lex->sql_command != SQLCOM_SELECT
+			&& lock_type != TL_IGNORE)) {
 
 		/* The OR cases above are in this order:
 		1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
@@ -6598,15 +6848,21 @@
 		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;
+
+		isolation_level = trx->isolation_level;
 
-			/* In case we have innobase_locks_unsafe_for_binlog
-			option set and isolation level of the transaction
+		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
@@ -6670,13 +6926,13 @@
 		stored function call (MySQL does have thd->in_lock_tables
 		TRUE there). */
 
-    		if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
-		    && lock_type <= TL_WRITE)
-		    && !(thd->in_lock_tables
-			    && thd->lex->sql_command == SQLCOM_LOCK_TABLES)
-		    && !thd->tablespace_op
-		    && thd->lex->sql_command != SQLCOM_TRUNCATE
-		    && thd->lex->sql_command != SQLCOM_OPTIMIZE
+		if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
+		&& lock_type <= TL_WRITE)
+		&& !(thd->in_lock_tables
+			&& thd->lex->sql_command == SQLCOM_LOCK_TABLES)
+		&& !thd->tablespace_op
+		&& thd->lex->sql_command != SQLCOM_TRUNCATE
+		&& thd->lex->sql_command != SQLCOM_OPTIMIZE
 
 #ifdef __WIN__
                 /* For alter table on win32 for succesful operation
@@ -6685,13 +6941,13 @@
                 TL_WRITE is lifted to TL_WRITE_ALLOW_WRITE, which causes
                 race condition when several clients do alter table
                 simultaneously (bug #17264). This fix avoids the problem. */
-		    && thd->lex->sql_command != SQLCOM_ALTER_TABLE
+                && thd->lex->sql_command != SQLCOM_ALTER_TABLE
 #endif
 
-		    && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
+		&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
 
 			lock_type = TL_WRITE_ALLOW_WRITE;
-      		}
+		}
 
 		/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
 		MySQL would use the lock TL_READ_NO_INSERT on t2, and that
@@ -6730,17 +6986,18 @@
 				timeout */
 	longlong*	ret)	/* out: auto-inc value */
 {
-  	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
-    	longlong        auto_inc;
+	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
+	longlong	auto_inc;
 	ulint		old_select_lock_type;
 	ibool		trx_was_not_started	= FALSE;
-  	int     	error;
+	int		error;
 
-  	ut_a(prebuilt);
-	ut_a(prebuilt->trx ==
-                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+	ut_a(prebuilt);
 	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;
 	}
@@ -6780,8 +7037,8 @@
 		goto func_exit_early;
 	}
 
-  	(void) extra(HA_EXTRA_KEYREAD);
-  	index_init(table->s->next_number_index);
+	(void) extra(HA_EXTRA_KEYREAD);
+	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
@@ -6790,12 +7047,12 @@
 	column, our consistent read will not return the largest value. We
 	accept this flaw, since the deadlocks were a bigger trouble. */
 
-  	/* Fetch all the columns in the key */
+	/* Fetch all the columns in the key */
 
 	prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
 
 	old_select_lock_type = prebuilt->select_lock_type;
-  	prebuilt->select_lock_type = LOCK_NONE;
+	prebuilt->select_lock_type = LOCK_NONE;
 
 	/* Eliminate an InnoDB error print that happens when we try to SELECT
 	from a table when no table has been locked in ::external_lock(). */
@@ -6804,9 +7061,9 @@
 	error = index_last(table->record[1]);
 
 	prebuilt->trx->n_mysql_tables_in_use--;
-  	prebuilt->select_lock_type = old_select_lock_type;
+	prebuilt->select_lock_type = old_select_lock_type;
 
-  	if (error) {
+	if (error) {
 		if (error == HA_ERR_END_OF_FILE) {
 			/* The table was empty, initialize to 1 */
 			auto_inc = 1;
@@ -6816,25 +7073,31 @@
 			/* This should not happen in a consistent read */
 		  sql_print_error("Consistent read of auto-inc column "
 				  "returned %lu", (ulong) error);
-  			auto_inc = -1;
+			auto_inc = -1;
 
-  			goto func_exit;
-  		}
-  	} else {
+			goto func_exit;
+		}
+	} else {
 		/* Initialize to max(col) + 1; we use
 		'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'. */
-
-    		auto_inc = (longlong) table->found_next_number_field->
-                        	val_int_offset(table->s->rec_buff_length) + 1;
-  	}
+		'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);
 
 func_exit:
-  	(void) extra(HA_EXTRA_NO_KEYREAD);
+	(void) extra(HA_EXTRA_NO_KEYREAD);
 
 	index_end();
 
@@ -6853,23 +7116,30 @@
 		innobase_commit_low(prebuilt->trx);
 	}
 
- 	return(error);
+	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;
+	longlong	nr;
+	int		error;
+
+	/* Prepare prebuilt->trx in the table handle */
+	update_thd(current_thd);
 
 	error = innobase_read_and_init_auto_inc(&nr);
 
@@ -6881,10 +7151,13 @@
 		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 */
@@ -6894,7 +7167,9 @@
 	DBUG_ENTER("ha_innobase::reset_auto_increment");
 
 	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
-  	int     	error;
+	int		error;
+
+	update_thd(current_thd);
 
 	error = row_lock_table_autoinc_for_mysql(prebuilt);
 
@@ -6913,7 +7188,7 @@
 bool
 ha_innobase::get_error_message(int error, String *buf)
 {
-	trx_t*	    trx = check_trx_exists(current_thd);
+	trx_t*	trx = check_trx_exists(ht, current_thd);
 
 	buf->copy(trx->detailed_error, strlen(trx->detailed_error),
 		system_charset_info);
@@ -6936,14 +7211,14 @@
 	const mysql_byte* ref2)	/* in: an (internal) primary key value in the
 				MySQL key value format */
 {
-	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 	enum_field_types mysql_type;
 	Field*		field;
 	KEY_PART_INFO*	key_part;
 	KEY_PART_INFO*	key_part_end;
 	uint		len1;
 	uint		len2;
-	int 		result;
+	int		result;
 
 	if (prebuilt->clust_index_was_generated) {
 		/* The 'ref' is an InnoDB row id */
@@ -6963,10 +7238,10 @@
 		field = key_part->field;
 		mysql_type = field->type();
 
-		if (mysql_type == FIELD_TYPE_TINY_BLOB
-		    || mysql_type == FIELD_TYPE_MEDIUM_BLOB
-		    || mysql_type == FIELD_TYPE_BLOB
-		    || mysql_type == FIELD_TYPE_LONG_BLOB) {
+		if (mysql_type == MYSQL_TYPE_TINY_BLOB
+			|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
+			|| mysql_type == MYSQL_TYPE_BLOB
+			|| mysql_type == MYSQL_TYPE_LONG_BLOB) {
 
 			/* In the MySQL key value format, a column prefix of
 			a BLOB is preceded by a 2-byte length field */
@@ -6977,8 +7252,8 @@
 			ref1 += 2;
 			ref2 += 2;
 			result = ((Field_blob*)field)->cmp(
-						    (const char*)ref1, len1,
-			                            (const char*)ref2, len2);
+				(const char*)ref1, len1,
+				(const char*)ref2, len2);
 		} else {
 			result = field->key_cmp(ref1, ref2);
 		}
@@ -7004,10 +7279,10 @@
 ulonglong
 ha_innobase::get_mysql_bin_log_pos()
 {
-  	/* trx... is ib_longlong, which is a typedef for a 64-bit integer
+	/* trx... is ib_longlong, which is a typedef for a 64-bit integer
 	(__int64 or longlong) so it's ok to cast it to ulonglong. */
 
-  	return(trx_sys_mysql_bin_log_pos);
+	return(trx_sys_mysql_bin_log_pos);
 }
 
 extern "C" {
@@ -7029,7 +7304,7 @@
 	ulint prefix_len,	/* in: prefix length in bytes of the index
 				(this has to be divided by mbmaxlen to get the
 				number of CHARACTERS n in the prefix) */
-	ulint data_len,         /* in: length of the string in bytes */
+	ulint data_len,		/* in: length of the string in bytes */
 	const char* str)	/* in: character string */
 {
 	ulint char_length;	/* character length in bytes */
@@ -7086,7 +7361,6 @@
 }
 }
 
-extern "C" {
 /**********************************************************************
 This function returns true if
 
@@ -7096,33 +7370,34 @@
 2) SQL-query in the current thread
 is INSERT ON DUPLICATE KEY UPDATE.
 
-NOTE that /mysql/innobase/row/row0ins.c must contain the
+NOTE that storage/innobase/row/row0ins.c must contain the
 prototype for this function ! */
-
+extern "C"
 ibool
 innobase_query_is_update(void)
 /*==========================*/
 {
-	THD*	thd;
-
-	thd = (THD *)innobase_current_thd();
-
-	if (thd->lex->sql_command == SQLCOM_REPLACE ||
-	    thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
-	    (thd->lex->sql_command == SQLCOM_LOAD &&
-	     thd->lex->duplicates == DUP_REPLACE)) {
-
-		return(1);
-	}
-
-	if (thd->lex->sql_command == SQLCOM_INSERT &&
-	    thd->lex->duplicates  == DUP_UPDATE) {
+	THD*	thd = current_thd;
 
-		return(1);
+	if (!thd) {
+		/* InnoDB's internal threads may run InnoDB stored procedures
+		that call this function. Then current_thd is not defined
+		(it is probably NULL). */
+
+		return(FALSE);
+	}
+
+	switch (thd->lex->sql_command) {
+	case SQLCOM_REPLACE:
+	case SQLCOM_REPLACE_SELECT:
+		return(TRUE);
+	case SQLCOM_LOAD:
+		return(thd->lex->duplicates == DUP_REPLACE);
+	case SQLCOM_INSERT:
+		return(thd->lex->duplicates == DUP_UPDATE);
+	default:
+		return(FALSE);
 	}
-
-	return(0);
-}
 }
 
 /***********************************************************************
@@ -7132,45 +7407,48 @@
 innobase_xa_prepare(
 /*================*/
 			/* out: 0 or error number */
+        handlerton *hton,
 	THD*	thd,	/* in: handle to the MySQL thread of the user
 			whose XA transaction should be prepared */
 	bool	all)	/* in: TRUE - commit transaction
 			FALSE - the current SQL statement ended */
 {
 	int error = 0;
-        trx_t* trx = check_trx_exists(thd);
-
-        if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
-
-                /* For ibbackup to work the order of transactions in binlog
-                and InnoDB must be the same. Consider the situation
+	trx_t* trx = check_trx_exists(hton, thd);
 
-                  thread1> prepare; write to binlog; ...
-                          <context switch>
-                  thread2> prepare; write to binlog; commit
-                  thread1>                           ... commit
-
-                To ensure this will not happen we're taking the mutex on
-                prepare, and releasing it on commit.
-
-                Note: only do it for normal commits, done via ha_commit_trans.
-                If 2pc protocol is executed by external transaction
-                coordinator, it will be just a regular MySQL client
-                executing XA PREPARE and XA COMMIT commands.
-                In this case we cannot know how many minutes or hours
-                will be between XA PREPARE and XA COMMIT, and we don't want
-                to block for undefined period of time.
-                */
-                pthread_mutex_lock(&prepare_commit_mutex);
-                trx->active_trans = 2;
-        }
+	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
+
+		  thread1> prepare; write to binlog; ...
+			  <context switch>
+		  thread2> prepare; write to binlog; commit
+		  thread1>			     ... commit
+
+		To ensure this will not happen we're taking the mutex on
+		prepare, and releasing it on commit.
+
+		Note: only do it for normal commits, done via ha_commit_trans.
+		If 2pc protocol is executed by external transaction
+		coordinator, it will be just a regular MySQL client
+		executing XA PREPARE and XA COMMIT commands.
+		In this case we cannot know how many minutes or hours
+		will be between XA PREPARE and XA COMMIT, and we don't want
+		to block for undefined period of time.
+		*/
+		pthread_mutex_lock(&prepare_commit_mutex);
+		trx->active_trans = 2;
+	}
 
 	if (!thd->variables.innodb_support_xa) {
 
 		return(0);
 	}
 
-        trx->xid=thd->transaction.xid_state.xid;
+	trx->xid=thd->transaction.xid_state.xid;
 
 	/* Release a possible FIFO ticket and search latch. Since we will
 	reserve the kernel mutex, we have to release the search system latch
@@ -7185,16 +7463,16 @@
 	}
 
 	if (all
-	    || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
+		|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
 
-                /* We were instructed to prepare the whole transaction, or
-                this is an SQL statement end and autocommit is on */
+		/* We were instructed to prepare the whole transaction, or
+		this is an SQL statement end and autocommit is on */
 
-                ut_ad(trx->active_trans);
+		ut_ad(trx->active_trans);
 
 		error = (int) trx_prepare_for_mysql(trx);
 	} else {
-	        /* We just mark the SQL statement ended and do not do a
+		/* We just mark the SQL statement ended and do not do a
 		transaction prepare */
 
 		if (trx->auto_inc_lock) {
@@ -7215,7 +7493,7 @@
 
 	srv_active_wake_master_thread();
 
-        return error;
+	return error;
 }
 
 /***********************************************************************
@@ -7226,7 +7504,8 @@
 /*================*/
 				/* out: number of prepared transactions
 				stored in xid_list */
-	XID*    xid_list, 	/* in/out: prepared transactions */
+        handlerton *hton,
+	XID*	xid_list,	/* in/out: prepared transactions */
 	uint	len)		/* in: number of slots in xid_list */
 {
 	if (len == 0 || xid_list == NULL) {
@@ -7245,6 +7524,7 @@
 innobase_commit_by_xid(
 /*===================*/
 			/* out: 0 or error number */
+        handlerton *hton,
 	XID*	xid)	/* in: X/Open XA transaction identification */
 {
 	trx_t*	trx;
@@ -7268,6 +7548,7 @@
 innobase_rollback_by_xid(
 /*=====================*/
 			/* out: 0 or error number */
+        handlerton *hton,
 	XID	*xid)	/* in: X/Open XA transaction identification */
 {
 	trx_t*	trx;
@@ -7288,12 +7569,13 @@
 using a cursor. */
 
 void*
-innobase_create_cursor_view(void)
-/*=============================*/
-			/* out: Pointer to cursor view or NULL */
+innobase_create_cursor_view(
+                          /* out: pointer to cursor view or NULL */
+        handlerton *hton, /* in: innobase hton */
+	THD* thd)	  /* in: user thread handle */
 {
 	return(read_cursor_view_create_for_mysql(
-					check_trx_exists(current_thd)));
+					check_trx_exists(hton, thd)));
 }
 
 /***********************************************************************
@@ -7303,10 +7585,11 @@
 
 void
 innobase_close_cursor_view(
-/*=======================*/
+        handlerton *hton,
+	THD*	thd,	/* in: user thread handle */
 	void*	curview)/* in: Consistent read view to be closed */
 {
-	read_cursor_view_close_for_mysql(check_trx_exists(current_thd),
+	read_cursor_view_close_for_mysql(check_trx_exists(hton, current_thd),
 						(cursor_view_t*) curview);
 }
 
@@ -7319,10 +7602,72 @@
 void
 innobase_set_cursor_view(
 /*=====================*/
+        handlerton *hton,
+	THD*	thd,	/* in: user thread handle */
 	void*	curview)/* in: Consistent cursor view to be set */
 {
-	read_cursor_set_for_mysql(check_trx_exists(current_thd),
+	read_cursor_set_for_mysql(check_trx_exists(hton, current_thd),
 						(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 };
+
+mysql_declare_plugin(innobase)
+{
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &innobase_storage_engine,
+  innobase_hton_name,
+  "Innobase OY",
+  "Supports transactions, row-level locking, and foreign keys",
+  PLUGIN_LICENSE_GPL,
+  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

--- 1.158/include/my_global.h	2007-02-22 10:53:25 +02:00
+++ 1.159/include/my_global.h	2007-02-22 17:56:57 +02:00
@@ -932,7 +932,6 @@
 #define my_offsetof(TYPE, MEMBER) \
         ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10))
 
-
 #define NullS		(char *) 0
 /* Nowdays we do not support MessyDos */
 #ifndef NEAR

--- 1.268/client/mysqltest.c	2007-02-22 10:50:28 +02:00
+++ 1.269/client/mysqltest.c	2007-02-22 17:48:11 +02:00
@@ -6284,7 +6284,8 @@
 
 
 void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
-                            const char *str, int len)
+                            const char *str,
+                            int len __attribute__((unused)))
 {
   reg1 REPLACE *rep_pos;
   reg2 REPLACE_STRING *rep_str;
@@ -6675,7 +6676,7 @@
         we need at least what we have so far in the buffer + the part
         before this match
       */
-      need_buf_len= (res_p - buf) + subs[0].rm_so;
+      need_buf_len= (res_p - buf) + (int) subs[0].rm_so;
 
       /* on this pass, calculate the memory for the result buffer */
       while (expr_p < replace_end)
@@ -6685,17 +6686,17 @@
 
         if (c == '\\' && expr_p + 1 < replace_end)
         {
-          back_ref_num= expr_p[1] - '0';
+          back_ref_num= (int) (expr_p[1] - '0');
         }
 
         /* found a valid back_ref (eg. \1)*/
         if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
         {
-          int start_off,end_off;
+          regoff_t start_off, end_off;
           if ((start_off=subs[back_ref_num].rm_so) > -1 &&
               (end_off=subs[back_ref_num].rm_eo) > -1)
           {
-            need_buf_len += (end_off - start_off);
+            need_buf_len += (int) (end_off - start_off);
           }
           expr_p += 2;
         }
@@ -6715,7 +6716,7 @@
         /* copy the pre-match part */
         if (subs[0].rm_so)
         {
-          memcpy(res_p, str_p, subs[0].rm_so);
+          memcpy(res_p, str_p, (size_t) subs[0].rm_so);
           res_p+= subs[0].rm_so;
         }
 

--- 1.26/server-tools/instance-manager/mysql_connection.cc	2007-01-27 03:46:39 +02:00
+++ 1.27/server-tools/instance-manager/mysql_connection.cc	2007-02-22 17:56:57 +02:00
@@ -87,7 +87,7 @@
   /* Initialize random number generator */
   {
     ulong seed1= (ulong) &rand_st + rand();
-    ulong seed2= (ulong) rand() + time(0);
+    ulong seed2= (ulong) rand() + (ulong) time(0);
     randominit(&rand_st, seed1, seed2);
   }
 

--- 1.80/strings/decimal.c	2007-01-24 19:57:04 +02:00
+++ 1.81/strings/decimal.c	2007-02-22 17:48:13 +02:00
@@ -1362,6 +1362,7 @@
   {
     int i=dig2bytes[intg0x];
     dec1 x;
+    LINT_INIT(x);
     switch (i)
     {
       case 1: x=mi_sint1korr(from); break;
@@ -1403,6 +1404,7 @@
   {
     int i=dig2bytes[frac0x];
     dec1 x;
+    LINT_INIT(x);
     switch (i)
     {
       case 1: x=mi_sint1korr(from); break;
@@ -1489,6 +1491,7 @@
 
   sanity(to);
 
+  LINT_INIT(round_digit);
   switch (mode) {
   case HALF_UP:
   case HALF_EVEN:       round_digit=5; break;

--- 1.21/extra/yassl/include/openssl/ssl.h	2007-01-29 18:54:36 +02:00
+++ 1.22/extra/yassl/include/openssl/ssl.h	2007-02-22 17:48:11 +02:00
@@ -33,7 +33,6 @@
 #include "opensslv.h" /* for version number */
 #include "rsa.h"
 
-
 #define YASSL_VERSION "1.5.8"
 
 
@@ -190,11 +189,16 @@
     EVP_R_BAD_DECRYPT = 2
 };
 
+#ifdef WIN
+    typedef SOCKET socket_t;
+#else
+    typedef int socket_t;
+#endif
 
 
 SSL_CTX* SSL_CTX_new(SSL_METHOD*);
 SSL* SSL_new(SSL_CTX*);
-int  SSL_set_fd (SSL*, int);
+int  SSL_set_fd (SSL*, socket_t);
 int  SSL_connect(SSL*);
 int  SSL_write(SSL*, const void*, int);
 int  SSL_read(SSL*, void*, int);

--- 1.30/extra/yassl/src/ssl.cpp	2007-02-22 10:53:25 +02:00
+++ 1.31/extra/yassl/src/ssl.cpp	2007-02-22 17:48:11 +02:00
@@ -233,7 +233,7 @@
 }
 
 
-int SSL_set_fd(SSL* ssl, int fd)
+int SSL_set_fd(SSL* ssl, socket_t fd)
 {
     ssl->useSocket().set_fd(fd);
     return SSL_SUCCESS;

--- 1.198/sql/sql_prepare.cc	2007-02-22 10:53:28 +02:00
+++ 1.199/sql/sql_prepare.cc	2007-02-22 17:48:12 +02:00
@@ -2054,6 +2054,7 @@
   uint query_len;
   DBUG_ENTER("mysql_sql_stmt_prepare");
   DBUG_ASSERT(thd->protocol == &thd->protocol_simple);
+  LINT_INIT(query_len);
 
   if ((stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
   {
Thread
bk commit into 5.1 tree (monty:1.2453)monty22 Feb