From 65badfff1a6dec4de5bf2d29cf143c72b5dd8830 Mon Sep 17 00:00:00 2001
From: "monty@hundin.mysql.fi" <>
Date: Thu, 7 Nov 2002 04:02:37 +0200
Subject: [PATCH] Put temporary files in binlog cache when using BEGIN/COMMIT
 Let MySQL 4.0 read 4.1 .frm files without 4.1 specific extensions New
 variables @@rand_seed1 and @@rand_seed2 (used by replication) DROP TEMPORARY
 TABLE

---
 mysql-test/r/rpl_log.result   |   2 +-
 mysql-test/r/variables.result |   4 ++
 mysql-test/t/variables.test   |   4 ++
 sql/field.cc                  |  11 +++-
 sql/field.h                   |   6 +-
 sql/item_func.cc              |   2 +-
 sql/log.cc                    |  18 ++++--
 sql/log_event.cc              | 100 ++++++++++++++++++----------------
 sql/log_event.h               |  50 +++++++++--------
 sql/set_var.cc                |  17 ++++++
 sql/set_var.h                 |  17 ++++++
 sql/slave.cc                  |   4 +-
 sql/sql_acl.cc                |   2 +-
 sql/sql_base.cc               |  28 ++++------
 sql/sql_class.h               |   4 +-
 sql/sql_db.cc                 |   4 +-
 sql/sql_delete.cc             |  57 +++++++++----------
 sql/sql_insert.cc             |  18 +++---
 sql/sql_lex.h                 |   2 +-
 sql/sql_load.cc               |  31 +++++++----
 sql/sql_parse.cc              |   6 +-
 sql/sql_rename.cc             |   2 +-
 sql/sql_repl.cc               |   5 +-
 sql/sql_repl.h                |   4 +-
 sql/sql_table.cc              |  55 ++++++++++++-------
 sql/sql_update.cc             |  19 ++++---
 sql/sql_yacc.yy               |  13 ++++-
 sql/table.cc                  |  76 +++++++++++++++++---------
 sql/unireg.cc                 |   1 +
 29 files changed, 342 insertions(+), 220 deletions(-)

diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
index 7d1843f95fc..835b5d6629a 100644
--- a/mysql-test/r/rpl_log.result
+++ b/mysql-test/r/rpl_log.result
@@ -72,7 +72,7 @@ show binlog events in 'slave-bin.001' from 4;
 Log_name	Pos	Event_type	Server_id	Orig_log_pos	Info
 slave-bin.001	4	Start	2	4	Server ver: VERSION, Binlog ver: 3
 slave-bin.001	79	Query	1	79	use test; create table t1(n int not null auto_increment primary key)
-slave-bin.001	172	Intvar	1	200	INSERT_ID=1
+slave-bin.001	172	Intvar	1	172	INSERT_ID=1
 slave-bin.001	200	Query	1	200	use test; insert into t1 values (NULL)
 slave-bin.001	263	Query	1	263	use test; drop table t1
 slave-bin.001	311	Query	1	311	use test; create table t1 (word char(20) not null)
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index ff0f94ab4a6..f8ac13477a9 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -170,6 +170,10 @@ convert_character_set	cp1251_koi8
 select @@timestamp>0;
 @@timestamp>0
 1
+set @@rand_seed1=10000000,@@rand_seed2=1000000;
+select ROUND(RAND(),5);
+ROUND(RAND(),5)
+0.02887
 set big_tables=OFFF;
 Variable 'big_tables' can't be set to the value of 'OFFF'
 set big_tables="OFFF";
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index e84a7fe404d..e21fbd975e6 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -93,6 +93,10 @@ set global character set default, session character set default;
 show variables like "convert_character_set";
 select @@timestamp>0;
 
+set @@rand_seed1=10000000,@@rand_seed2=1000000;
+select ROUND(RAND(),5);
+
+
 # The following should give errors
 
 --error 1231
diff --git a/sql/field.cc b/sql/field.cc
index 42ddcc3b9d2..eed165f0ed1 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4864,6 +4864,7 @@ uint pack_length_to_packflag(uint type)
 Field *make_field(char *ptr, uint32 field_length,
 		  uchar *null_pos, uchar null_bit,
 		  uint pack_flag,
+		  enum_field_types field_type,
 		  Field::utype unireg_check,
 		  TYPELIB *interval,
 		  const char *field_name,
@@ -4889,6 +4890,9 @@ Field *make_field(char *ptr, uint32 field_length,
       return new Field_blob(ptr,null_pos,null_bit,
 			    unireg_check, field_name, table,
 			    pack_length,f_is_binary(pack_flag) != 0);
+    if (f_is_geom(pack_flag))
+      return 0;
+
     if (interval)
     {
       if (f_is_enum(pack_flag))
@@ -4902,7 +4906,7 @@ Field *make_field(char *ptr, uint32 field_length,
     }
   }
 
-  switch ((enum enum_field_types) f_packtype(pack_flag)) {
+  switch (field_type) {
   case FIELD_TYPE_DECIMAL:
     return new Field_decimal(ptr,field_length,null_pos,null_bit,
 			     unireg_check, field_name, table,
@@ -4965,10 +4969,11 @@ Field *make_field(char *ptr, uint32 field_length,
     return new Field_datetime(ptr,null_pos,null_bit,
 			      unireg_check, field_name, table);
   case FIELD_TYPE_NULL:
-    default:					// Impossible (Wrong version)
     return new Field_null(ptr,field_length,unireg_check,field_name,table);
+  default:					// Impossible (Wrong version)
+    break;
   }
-  return 0;					// Impossible (Wrong version)
+  return 0;					// Impossible
 }
 
 
diff --git a/sql/field.h b/sql/field.h
index 4290f99ea3e..ba28a6a872e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1050,7 +1050,9 @@ public:
 
 Field *make_field(char *ptr, uint32 field_length,
 		  uchar *null_pos, uchar null_bit,
-		  uint pack_flag, Field::utype unireg_check,
+		  uint pack_flag,
+		  enum_field_types field_type,
+		  Field::utype unireg_check,
 		  TYPELIB *interval, const char *field_name,
 		  struct st_table *table);
 uint pack_length_to_packflag(uint type);
@@ -1073,6 +1075,7 @@ bool test_if_int(const char *str,int length);
 #define FIELDFLAG_INTERVAL		256
 #define FIELDFLAG_BITFIELD		512	// mangled with dec!
 #define FIELDFLAG_BLOB			1024	// mangled with dec!
+#define FIELDFLAG_GEOM			2048
 #define FIELDFLAG_LEFT_FULLSCREEN	8192
 #define FIELDFLAG_RIGHT_FULLSCREEN	16384
 #define FIELDFLAG_FORMAT_NUMBER		16384	// predit: ###,,## in output
@@ -1099,6 +1102,7 @@ bool test_if_int(const char *str,int length);
 #define f_is_enum(x)	((x) & FIELDFLAG_INTERVAL)
 #define f_is_bitfield(x)	((x) & FIELDFLAG_BITFIELD)
 #define f_is_blob(x)		(((x) & (FIELDFLAG_BLOB | FIELDFLAG_NUMBER)) == FIELDFLAG_BLOB)
+#define f_is_geom(x)		((x) & FIELDFLAG_GEOM)
 #define f_is_equ(x)		((x) & (1+2+FIELDFLAG_PACK+31*256))
 #define f_settype(x)		(((int) x) << FIELDFLAG_PACK_SHIFT)
 #define f_maybe_null(x)		(x & FIELDFLAG_MAYBE_NULL)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7da5435276d..fec0e448630 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1516,7 +1516,7 @@ void item_user_lock_release(ULL *ull)
     tmp.append("DO RELEASE_LOCK(\"");
     tmp.append(ull->key,ull->key_length);
     tmp.append("\")");
-    Query_log_event qev(current_thd,tmp.ptr(), tmp.length());
+    Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1);
     qev.error_code=0; // this query is always safe to run on slave
     mysql_bin_log.write(&qev);
   }
diff --git a/sql/log.cc b/sql/log.cc
index 32c0f4417f1..5dc1a677f76 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1017,9 +1017,13 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
 bool MYSQL_LOG::write(Log_event* event_info)
 {
   bool error=0;
+  DBUG_ENTER("MYSQL_LOG::write(event)");
   
   if (!inited)					// Can't use mutex if not init
-    return 0;
+  {
+    DBUG_PRINT("error",("not initied"));
+    DBUG_RETURN(0);
+  }
   pthread_mutex_lock(&LOCK_log);
 
   /* In most cases this is only called if 'is_open()' is true */
@@ -1040,7 +1044,8 @@ bool MYSQL_LOG::write(Log_event* event_info)
 	(db && !db_ok(db, binlog_do_db, binlog_ignore_db)))
     {
       VOID(pthread_mutex_unlock(&LOCK_log));
-      return 0;
+      DBUG_PRINT("error",("!db_ok"));
+      DBUG_RETURN(0);
     }
 
     error=1;
@@ -1078,7 +1083,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
       char buf[1024] = "SET CHARACTER SET ";
       char* p = strend(buf);
       p = strmov(p, thd->variables.convert_set->name);
-      Query_log_event e(thd, buf, (ulong)(p - buf));
+      Query_log_event e(thd, buf, (ulong)(p - buf), 0);
       e.set_log_pos(this);
       if (e.write(file))
 	goto err;
@@ -1126,7 +1131,7 @@ err:
   }
 
   pthread_mutex_unlock(&LOCK_log);
-  return error;
+  DBUG_RETURN(error);
 }
 
 
@@ -1156,6 +1161,7 @@ uint MYSQL_LOG::next_file_id()
 bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
 {
   VOID(pthread_mutex_lock(&LOCK_log));
+  DBUG_ENTER("MYSQL_LOG::write(cache");
   
   if (is_open())				// Should always be true
   {
@@ -1214,7 +1220,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
     signal_update();
   }
   VOID(pthread_mutex_unlock(&LOCK_log));
-  return 0;
+  DBUG_RETURN(0);
 
 err:
   if (!write_error)
@@ -1223,7 +1229,7 @@ err:
     sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
   }
   VOID(pthread_mutex_unlock(&LOCK_log));
-  return 1;
+  DBUG_RETURN(1);
 }
 
 
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 871f72acbae..12f97d825a6 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -131,22 +131,25 @@ const char* Log_event::get_type_str()
 }
 
 #ifndef MYSQL_CLIENT
-Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
-  :exec_time(0), flags(flags_arg), cached_event_len(0),
-   temp_buf(0), thd(thd_arg)
+Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
+  :temp_buf(0), exec_time(0), cached_event_len(0), flags(flags_arg), 
+   thd(thd_arg)
 {
-  if (thd)
-  {
-    server_id = thd->server_id;
-    when = thd->start_time;
-    log_pos = thd->log_pos;
-  }
-  else
-  {
-    server_id = ::server_id;
-    when = time(NULL);
-    log_pos=0;
-  }
+  server_id = thd->server_id;
+  when = thd->start_time;
+  log_pos = thd->log_pos;
+  cache_stmt= (using_trans &&
+	       (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+}
+
+
+Log_event::Log_event()
+  :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0),
+   thd(0)
+{
+  server_id = ::server_id;
+  when = time(NULL);
+  log_pos=0;
 }
 
 /*
@@ -179,7 +182,7 @@ static void cleanup_load_tmpdir()
 #endif
 
 Log_event::Log_event(const char* buf, bool old_format)
-  :cached_event_len(0), temp_buf(0)
+  :temp_buf(0), cached_event_len(0), cache_stmt(0)
 {
   when = uint4korr(buf);
   server_id = uint4korr(buf + SERVER_ID_OFFSET);
@@ -350,14 +353,12 @@ void Intvar_log_event::pack_info(String* packet)
 
 void Rand_log_event::pack_info(String* packet)
 {
-  char buf1[256], buf[22];
-  String tmp(buf1, sizeof(buf1));
-  tmp.length(0);
-  tmp.append("randseed1=");
-  tmp.append(llstr(seed1, buf));
-  tmp.append(",randseed2=");
-  tmp.append(llstr(seed2, buf));
-  net_store_data(packet, tmp.ptr(), tmp.length());
+  char buf1[256], *pos;
+  pos=strmov(buf1,"rand_seed1=");
+  pos=int10_to_str((long) seed1, pos, 10);
+  pos=strmov(pos, ",rand_seed2=");
+  pos=int10_to_str((long) seed2, pos, 10);
+  net_store_data(packet, buf1, (uint) (pos-buf1));
 }
 
 void Slave_log_event::pack_info(String* packet)
@@ -783,12 +784,10 @@ int Rotate_log_event::write_data(IO_CACHE* file)
 #ifndef MYSQL_CLIENT
 Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
 				 ulong query_length, bool using_trans)
-  :Log_event(thd_arg), data_buf(0), query(query_arg),  db(thd_arg->db),
-  q_len((uint32) query_length),
+  :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg),
+   db(thd_arg->db), q_len((uint32) query_length),
   error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
-  thread_id(thd_arg->thread_id),
-  cache_stmt(using_trans &&
-	     (thd_arg->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+  thread_id(thd_arg->thread_id)
 {
   time_t end_time;
   time(&end_time);
@@ -963,8 +962,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
     print_header(file);
     fprintf(file, "\tRand\n");
   }
-  fprintf(file, "SET RAND SEED1=%s;\n", llstr(seed1, llbuff));
-  fprintf(file, "SET RAND SEED2=%s;\n", llstr(seed2, llbuff));
+  fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n",
+	  llstr(seed1, llbuff),llstr(seed2, llbuff));
   fflush(file);
 }
 #endif
@@ -1093,8 +1092,10 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
 Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
 			       const char* db_arg, const char* table_name_arg,
 			       List<Item>& fields_arg,
-			       enum enum_duplicates handle_dup)
-  :Log_event(thd),thread_id(thd->thread_id), num_fields(0),fields(0),
+			       enum enum_duplicates handle_dup,
+			       bool using_trans)
+  :Log_event(thd, 0, using_trans),thread_id(thd->thread_id),
+  num_fields(0),fields(0),
   field_lens(0),field_block_len(0),
   table_name(table_name_arg ? table_name_arg : ""),
   db(db_arg), fname(ex->file_name)
@@ -1332,7 +1333,7 @@ void Load_log_event::set_fields(List<Item> &fields)
 
 Slave_log_event::Slave_log_event(THD* thd_arg,
 				 struct st_relay_log_info* rli):
-  Log_event(thd_arg),mem_pool(0),master_host(0)
+  Log_event(thd_arg,0,0),mem_pool(0),master_host(0)
 {
   DBUG_ENTER("Slave_log_event");
   if (!rli->inited)				// QQ When can this happen ?
@@ -1432,11 +1433,13 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len)
 }
 
 #ifndef MYSQL_CLIENT
-Create_file_log_event::Create_file_log_event(THD* thd_arg, sql_exchange* ex,
-		 const char* db_arg, const char* table_name_arg,
-		 List<Item>& fields_arg, enum enum_duplicates handle_dup,
-			char* block_arg, uint block_len_arg)
-  :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup),
+Create_file_log_event::
+Create_file_log_event(THD* thd_arg, sql_exchange* ex,
+		      const char* db_arg, const char* table_name_arg,
+		      List<Item>& fields_arg, enum enum_duplicates handle_dup,
+		      char* block_arg, uint block_len_arg, bool using_trans)
+  :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup,
+		  using_trans),
    fake_base(0),block(block_arg),block_len(block_len_arg),
    file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
 {
@@ -1532,9 +1535,10 @@ void Create_file_log_event::pack_info(String* packet)
 
 #ifndef MYSQL_CLIENT  
 Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
-					       uint block_len_arg)
-  :Log_event(thd_arg), block(block_arg),block_len(block_len_arg),
-   file_id(thd_arg->file_id)
+					       uint block_len_arg,
+					       bool using_trans)
+  :Log_event(thd_arg,0, using_trans), block(block_arg),
+   block_len(block_len_arg), file_id(thd_arg->file_id)
 {
 }
 #endif  
@@ -1578,8 +1582,8 @@ void Append_block_log_event::pack_info(String* packet)
   net_store_data(packet, buf1);
 }
 
-Delete_file_log_event::Delete_file_log_event(THD* thd_arg)
-  :Log_event(thd_arg),file_id(thd_arg->file_id)
+Delete_file_log_event::Delete_file_log_event(THD* thd_arg, bool using_trans)
+  :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id)
 {
 }
 #endif  
@@ -1624,14 +1628,14 @@ void Delete_file_log_event::pack_info(String* packet)
 
 
 #ifndef MYSQL_CLIENT  
-Execute_load_log_event::Execute_load_log_event(THD* thd_arg)
-  :Log_event(thd_arg),file_id(thd_arg->file_id)
+Execute_load_log_event::Execute_load_log_event(THD* thd_arg, bool using_trans)
+  :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id)
 {
 }
 #endif  
   
-Execute_load_log_event::Execute_load_log_event(const char* buf,int len)
-  :Log_event(buf, 0),file_id(0)
+Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
+  :Log_event(buf, 0), file_id(0)
 {
   if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
     return;
diff --git a/sql/log_event.h b/sql/log_event.h
index 2a133becbad..69a70d535ec 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -224,18 +224,19 @@ struct st_relay_log_info;
 class Log_event
 {
 public:
+  my_off_t log_pos;
+  char *temp_buf;
   time_t when;
   ulong exec_time;
   uint32 server_id;
-  my_off_t log_pos;
+  uint cached_event_len;
   uint16 flags;
-  int cached_event_len;
-  char* temp_buf;
-
+  bool cache_stmt;
 #ifndef MYSQL_CLIENT
   THD* thd;
 
-  Log_event(THD* thd_arg, uint16 flags_arg = 0);
+  Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt);
+  Log_event();
   // if mutex is 0, the read will proceed without mutex
   static Log_event* read_log_event(IO_CACHE* file,
 				   pthread_mutex_t* log_lock,
@@ -278,7 +279,7 @@ public:
   { return 0; }
   virtual Log_event_type get_type_code() = 0;
   virtual bool is_valid() = 0;
-  virtual bool get_cache_stmt() { return 0; }
+  inline bool get_cache_stmt() { return cache_stmt; }
   Log_event(const char* buf, bool old_format);
   virtual ~Log_event() { free_temp_buf();}
   void register_temp_buf(char* buf) { temp_buf = buf; }
@@ -320,14 +321,12 @@ public:
   uint16 error_code;
   ulong thread_id;
 #ifndef MYSQL_CLIENT
-  bool cache_stmt;
 
   Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
-		  bool using_trans=0);
+		  bool using_trans);
   const char* get_db() { return db; }
   void pack_info(String* packet);
   int exec_event(struct st_relay_log_info* rli);
-  bool get_cache_stmt() { return cache_stmt; }
 #else
   void print(FILE* file, bool short_form = 0, char* last_db = 0);
 #endif
@@ -404,14 +403,15 @@ public:
   const char* fname;
   uint32 skip_lines;
   sql_ex_info sql_ex;
-  
+
 #ifndef MYSQL_CLIENT
   String field_lens_buf;
   String fields_buf;
   
   Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
 		 const char* table_name_arg,
-		 List<Item>& fields_arg, enum enum_duplicates handle_dup);
+		 List<Item>& fields_arg, enum enum_duplicates handle_dup,
+		 bool using_trans);
   void set_fields(List<Item> &fields_arg);
   void pack_info(String* packet);
   const char* get_db() { return db; }
@@ -427,8 +427,10 @@ public:
   Load_log_event(const char* buf, int event_len, bool old_format);
   ~Load_log_event()
   {}
-  Log_event_type get_type_code() { return sql_ex.new_format() ?
-				     NEW_LOAD_EVENT: LOAD_EVENT; }
+  Log_event_type get_type_code()
+  {
+    return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
+  }
   int write_data_header(IO_CACHE* file); 
   int write_data_body(IO_CACHE* file); 
   bool is_valid() { return table_name != 0; }
@@ -454,7 +456,7 @@ public:
   char server_version[ST_SERVER_VER_LEN];
 
 #ifndef MYSQL_CLIENT
-  Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
+  Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION)
   {
     created = (uint32) when;
     memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
@@ -485,7 +487,7 @@ public:
 
 #ifndef MYSQL_CLIENT  
   Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
-    :Log_event(thd_arg),val(val_arg),type(type_arg)
+    :Log_event(),val(val_arg),type(type_arg)
   {}
   void pack_info(String* packet);
   int exec_event(struct st_relay_log_info* rli);
@@ -515,7 +517,7 @@ class Rand_log_event: public Log_event
 
 #ifndef MYSQL_CLIENT
   Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
-    :Log_event(thd_arg),seed1(seed1_arg),seed2(seed2_arg)
+    :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
   {}
   void pack_info(String* packet);
   int exec_event(struct st_relay_log_info* rli);
@@ -536,7 +538,7 @@ class Stop_log_event: public Log_event
 {
 public:
 #ifndef MYSQL_CLIENT  
-  Stop_log_event() :Log_event((THD*)0)
+  Stop_log_event() :Log_event()
   {}
   int exec_event(struct st_relay_log_info* rli);
 #else
@@ -561,8 +563,9 @@ public:
   bool alloced;
 #ifndef MYSQL_CLIENT  
   Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
-		   uint ident_len_arg = 0,ulonglong pos_arg = 4)
-    : Log_event(thd_arg), new_log_ident(new_log_ident_arg),
+		   uint ident_len_arg = 0,
+		   ulonglong pos_arg = LOG_EVENT_OFFSET)
+    :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg),
     pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
 			   (uint) strlen(new_log_ident_arg)), alloced(0)
   {}
@@ -606,7 +609,8 @@ public:
 			const char* table_name_arg,
 			List<Item>& fields_arg,
 			enum enum_duplicates handle_dup,
-			char* block_arg, uint block_len_arg);
+			char* block_arg, uint block_len_arg,
+			bool using_trans);
   void pack_info(String* packet);
   int exec_event(struct st_relay_log_info* rli);
 #else
@@ -651,7 +655,7 @@ public:
   
 #ifndef MYSQL_CLIENT
   Append_block_log_event(THD* thd, char* block_arg,
-			 uint block_len_arg);
+			 uint block_len_arg, bool using_trans);
   int exec_event(struct st_relay_log_info* rli);
   void pack_info(String* packet);
 #else
@@ -673,7 +677,7 @@ public:
   uint file_id;
   
 #ifndef MYSQL_CLIENT
-  Delete_file_log_event(THD* thd);
+  Delete_file_log_event(THD* thd, bool using_trans);
   void pack_info(String* packet);
   int exec_event(struct st_relay_log_info* rli);
 #else
@@ -694,7 +698,7 @@ public:
   uint file_id;
   
 #ifndef MYSQL_CLIENT
-  Execute_load_log_event(THD* thd);
+  Execute_load_log_event(THD* thd, bool using_trans);
   void pack_info(String* packet);
   int exec_event(struct st_relay_log_info* rli);
 #else
diff --git a/sql/set_var.cc b/sql/set_var.cc
index a992ddf6044..ce85a81594c 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -283,6 +283,8 @@ static sys_var_last_insert_id	sys_identity("identity");
 static sys_var_insert_id	sys_insert_id("insert_id");
 /* alias for last_insert_id() to be compatible with Sybase */
 static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter");
+static sys_var_rand_seed1	sys_rand_seed1("rand_seed1");
+static sys_var_rand_seed2	sys_rand_seed2("rand_seed2");
 
 
 /*
@@ -351,6 +353,8 @@ sys_var *sys_variables[]=
   &sys_query_cache_type,
 #endif /* HAVE_QUERY_CACHE */
   &sys_quote_show_create,
+  &sys_rand_seed1,
+  &sys_rand_seed2,
   &sys_read_buff_size,
   &sys_read_rnd_buff_size,
   &sys_rpl_recovery_rank,
@@ -1043,6 +1047,19 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
 }
 
 
+bool sys_var_rand_seed1::update(THD *thd, set_var *var)
+{
+  thd->rand.seed1=var->value->val_int();
+  return 0;
+}
+
+bool sys_var_rand_seed2::update(THD *thd, set_var *var)
+{
+  thd->rand.seed2=var->value->val_int();
+  return 0;
+}
+
+
 /*
   Functions to update thd->options bits
 */
diff --git a/sql/set_var.h b/sql/set_var.h
index c43cdbfd63e..a171c4f5e76 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -332,6 +332,23 @@ public:
 };
 
 
+class sys_var_rand_seed1 :public sys_var
+{
+public:
+  sys_var_rand_seed1(const char *name_arg) :sys_var(name_arg) {}
+  bool update(THD *thd, set_var *var);
+  bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+class sys_var_rand_seed2 :public sys_var
+{
+public:
+  sys_var_rand_seed2(const char *name_arg) :sys_var(name_arg) {}
+  bool update(THD *thd, set_var *var);
+  bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+
 class sys_var_thd_conv_charset :public sys_var_thd
 {
 public:
diff --git a/sql/slave.cc b/sql/slave.cc
index 620523dd47f..5d82f34bfab 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2252,7 +2252,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
      in the loop
   */
   {
-    Append_block_log_event aev(thd,0,0);
+    Append_block_log_event aev(thd,0,0,0);
   
     for (;;)
     {
@@ -2265,7 +2265,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
       if (unlikely(!num_bytes)) /* eof */
       {
 	send_ok(net); /* 3.23 master wants it */
-	Execute_load_log_event xev(thd);
+	Execute_load_log_event xev(thd,0);
 	xev.log_pos = mi->master_log_pos;
 	if (unlikely(mi->rli.relay_log.append(&xev)))
 	{
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 1694e662b52..dc59f3f3137 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1091,7 +1091,7 @@ bool change_password(THD *thd, const char *host, const char *user,
 		acl_user->host.hostname ? acl_user->host.hostname : "",
 		new_password));
   mysql_update_log.write(thd, buff, query_length);
-  Query_log_event qinfo(thd, buff, query_length);
+  Query_log_event qinfo(thd, buff, query_length, 0);
   mysql_bin_log.write(&qinfo);
   DBUG_RETURN(0);
 }
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3b46c53f75c..838cf70f08d 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -539,26 +539,20 @@ void close_temporary_tables(THD *thd)
 {
   TABLE *table,*next;
   char *query, *end;
-  const uint init_query_buf_size = 11;		// "drop table "
   uint query_buf_size; 
   bool found_user_tables = 0;
 
+  if (!thd->temporary_tables)
+    return;
+  
   LINT_INIT(end);
-  query_buf_size = init_query_buf_size;
+  query_buf_size= 50;   // Enough for DROP ... TABLE
 
   for (table=thd->temporary_tables ; table ; table=table->next)
-  {
     query_buf_size += table->key_length;
-  }
-
-  if (query_buf_size == init_query_buf_size)
-    return; // no tables to close
 
   if ((query = alloc_root(&thd->mem_root, query_buf_size)))
-  {
-    memcpy(query, "drop table ", init_query_buf_size);
-    end = query + init_query_buf_size;
-  }
+    end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE ");
 
   for (table=thd->temporary_tables ; table ; table=next)
   {
@@ -567,12 +561,14 @@ void close_temporary_tables(THD *thd)
       // skip temporary tables not created directly by the user
       if (table->real_name[0] != '#')
       {
-	end = strxmov(end,table->table_cache_key,".",
-		      table->real_name,",", NullS);
-	// here we assume table_cache_key always starts
-	// with \0 terminated db name
+	/*
+	  Here we assume table_cache_key always starts
+	  with \0 terminated db name
+	*/
 	found_user_tables = 1;
       }
+      end = strxmov(end,table->table_cache_key,".",
+		    table->real_name,",", NullS);
     }
     next=table->next;
     close_temporary(table);
@@ -580,7 +576,7 @@ void close_temporary_tables(THD *thd)
   if (query && found_user_tables && mysql_bin_log.is_open())
   {
     /* The -1 is to remove last ',' */
-    Query_log_event qinfo(thd, query, (ulong)(end-query)-1);
+    Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
     qinfo.error_code=0;
     mysql_bin_log.write(&qinfo);
   }
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b8921964804..0f010b9de28 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -419,6 +419,7 @@ public:
   table_map  used_tables;
   USER_CONN *user_connect;
   ulong	     query_id,version, options,thread_id, col_access;
+  ulong	     rand_saved_seed1, rand_saved_seed2;
   long	     dbug_thread_id;
   pthread_t  real_id;
   uint	     current_tablenr,tmp_table,cond_count;
@@ -433,7 +434,6 @@ public:
   bool	     set_query_id,locked,count_cuted_fields,some_tables_deleted;
   bool	     no_errors, allow_sum_func, password, fatal_error;
   bool	     query_start_used,last_insert_id_used,insert_id_used,rand_used;
-  ulonglong  rand_saved_seed1, rand_saved_seed2;
   bool	     system_thread,in_lock_tables,global_read_lock;
   bool       query_error, bootstrap, cleanup_done;
   bool	     safe_to_cache_query;
@@ -805,7 +805,7 @@ public:
    uint num_of_tables;
    int error;
    thr_lock_type lock_option;
-   bool do_delete, not_trans_safe;
+   bool do_delete, transactional_tables, log_delayed, normal_tables;
  public:
    multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
 		uint num_of_tables);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index be193ee0b55..cde0c6cc31f 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -86,7 +86,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
       mysql_update_log.write(thd,thd->query, thd->query_length);
       if (mysql_bin_log.is_open())
       {
-	Query_log_event qinfo(thd, thd->query, thd->query_length);
+	Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
 	mysql_bin_log.write(&qinfo);
       }
     }
@@ -174,7 +174,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
       mysql_update_log.write(thd, thd->query, thd->query_length);
       if (mysql_bin_log.is_open())
       {
-	Query_log_event qinfo(thd, thd->query, thd->query_length);
+	Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
 	mysql_bin_log.write(&qinfo);
       }
       if (thd->query == path)
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index b40e0b7b093..1faa6e3250e 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -35,7 +35,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
   SQL_SELECT	*select=0;
   READ_RECORD	info;
   bool 		using_limit=limit != HA_POS_ERROR;
-  bool	        using_transactions;
+  bool		transactional_table, log_delayed;
   ha_rows	deleted;
   DBUG_ENTER("mysql_delete");
 
@@ -161,21 +161,22 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
     (void) table->file->extra(HA_EXTRA_NORMAL);
 
 cleanup:
-  using_transactions=table->file->has_transactions();
-  if (deleted && (error <= 0 || !using_transactions))
+  transactional_table= table->file->has_transactions();
+  log_delayed= (transactional_table || table->tmp_table);
+  if (deleted && (error <= 0 || !transactional_table))
   {
     mysql_update_log.write(thd,thd->query, thd->query_length);
     if (mysql_bin_log.is_open())
     {
       Query_log_event qinfo(thd, thd->query, thd->query_length, 
-			    using_transactions);
-      if (mysql_bin_log.write(&qinfo) && using_transactions)
+			    log_delayed);
+      if (mysql_bin_log.write(&qinfo) && transactional_table)
 	error=1;
     }
-    if (!using_transactions)
+    if (!log_delayed)
       thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
   }
-  if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0))
+  if (transactional_table && ha_autocommit_or_rollback(thd,error >= 0))
     error=1;
   if (deleted)
   {
@@ -214,9 +215,8 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
 			   uint num_of_tables_arg)
   : delete_tables (dt), thd(thd_arg), deleted(0),
     num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg),
-    do_delete(false)
+    do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
 {
-  not_trans_safe=false;
   tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
 }
 
@@ -266,8 +266,12 @@ multi_delete::initialize_tables(JOIN *join)
       /* Don't use KEYREAD optimization on this table */
       tbl->no_keyread=1;
       walk=walk->next;
-      if (!not_trans_safe && !tbl->file->has_transactions())
-	not_trans_safe=true;
+      if (tbl->file->has_transactions())
+	log_delayed= transactional_tables= 1;
+      else if (tbl->tmp_table != NO_TMP_TABLE)
+	log_delayed= 1;
+      else
+	normal_tables= 1;
     }
   }
   walk= delete_tables;
@@ -373,7 +377,7 @@ void multi_delete::send_error(uint errcode,const char *err)
     In all other cases do attempt deletes ...
   */
   if ((table_being_deleted->table->file->has_transactions() &&
-       table_being_deleted == delete_tables) || !not_trans_safe)
+       table_being_deleted == delete_tables) || !normal_tables)
     ha_rollback_stmt(thd);
   else if (do_delete)
   {
@@ -419,8 +423,7 @@ int multi_delete::do_deletes(bool from_send_error)
 
     READ_RECORD	info;
     init_read_record(&info,thd,table,NULL,0,0);
-    while (!(error=info.read_record(&info)) &&
-	   (!thd->killed ||  from_send_error || not_trans_safe))
+    while (!(error=info.read_record(&info)) && !thd->killed)
     {
       if ((error=table->file->delete_row(table->record[0])))
       {
@@ -453,11 +456,6 @@ bool multi_delete::send_eof()
 
   /* reset used flags */
   thd->proc_info="end";
-  if (error)
-  {
-    ::send_error(&thd->net);
-    return 1;
-  }
 
   /*
     Write the SQL statement to the binlog if we deleted
@@ -465,24 +463,25 @@ bool multi_delete::send_eof()
     was a non-transaction-safe table involved, since
     modifications in it cannot be rolled back.
   */
-  if (deleted || not_trans_safe)
+  if (deleted)
   {
     mysql_update_log.write(thd,thd->query,thd->query_length);
     if (mysql_bin_log.is_open())
     {
-      Query_log_event qinfo(thd, thd->query, thd->query_length);
-      if (mysql_bin_log.write(&qinfo) &&
-	  !not_trans_safe)
+      Query_log_event qinfo(thd, thd->query, thd->query_length,
+			    log_delayed);
+      if (mysql_bin_log.write(&qinfo) && !normal_tables)
 	error=1;  // Log write failed: roll back the SQL statement
     }
     /* Commit or rollback the current SQL statement */ 
     VOID(ha_autocommit_or_rollback(thd,error > 0));
-  }
-  if (deleted)
-  {
+
     query_cache_invalidate3(thd, delete_tables, 1);
   }
-  ::send_ok(&thd->net,deleted);
+  if (error)
+    ::send_error(&thd->net);
+  else
+    ::send_ok(&thd->net,deleted);
   return 0;
 }
 
@@ -565,6 +564,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
   *fn_ext(path)=0;				// Remove the .frm extension
   error= ha_create_table(path,&create_info,1) ? -1 : 0;
   query_cache_invalidate3(thd, table_list, 0); 
+
 end:
   if (!dont_send_ok)
   {
@@ -573,7 +573,8 @@ end:
       mysql_update_log.write(thd,thd->query,thd->query_length);
       if (mysql_bin_log.is_open())
       {
-	Query_log_event qinfo(thd, thd->query, thd->query_length);
+	Query_log_event qinfo(thd, thd->query, thd->query_length,
+			      thd->tmp_table);
 	mysql_bin_log.write(&qinfo);
       }
       send_ok(&thd->net);		// This should return record count
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index bd379bf688d..81178809f8f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -104,7 +104,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
   int error;
   bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
 		!(thd->master_access & SUPER_ACL));
-  bool using_transactions, bulk_insert=0;
+  bool transactional_table, log_delayed, bulk_insert=0;
   uint value_count;
   uint save_time_stamp;
   ulong counter = 1;
@@ -297,21 +297,23 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
       thd->insert_id(id);			// For update log
     else if (table->next_number_field)
       id=table->next_number_field->val_int();	// Return auto_increment value
-    using_transactions=table->file->has_transactions();
-    if ((info.copied || info.deleted) && (error <= 0 || !using_transactions))
+    
+    transactional_table= table->file->has_transactions();
+    log_delayed= (transactional_table || table->tmp_table);
+    if ((info.copied || info.deleted) && (error <= 0 || !transactional_table))
     {
       mysql_update_log.write(thd, thd->query, thd->query_length);
       if (mysql_bin_log.is_open())
       {
 	Query_log_event qinfo(thd, thd->query, thd->query_length,
-			      using_transactions);
-	if (mysql_bin_log.write(&qinfo) && using_transactions)
+			      log_delayed);
+	if (mysql_bin_log.write(&qinfo) && transactional_table)
 	  error=1;
       }
-      if (!using_transactions)
+      if (!log_delayed)
 	thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
     }
-    if (using_transactions)
+    if (transactional_table)
       error=ha_autocommit_or_rollback(thd,error);
     if (info.copied || info.deleted)
     {
@@ -1197,7 +1199,7 @@ bool delayed_insert::handle_inserts(void)
       mysql_update_log.write(&thd,row->query, row->query_length);
       if (using_bin_log)
       {
-	Query_log_event qinfo(&thd, row->query, row->query_length);
+	Query_log_event qinfo(&thd, row->query, row->query_length,0);
 	mysql_bin_log.write(&qinfo);
       }
     }
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 16ef7e750cd..54e72fafdd5 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -176,7 +176,7 @@ typedef struct st_lex
   enum enum_var_type option_type;
   uint grant,grant_tot_col,which_columns, union_option;
   thr_lock_type lock_option;
-  bool	drop_primary,drop_if_exists,local_file, olap;
+  bool	drop_primary, drop_if_exists, drop_temporary, local_file, olap;
   bool  in_comment,ignore_space,verbose,simple_alter;
   uint slave_thd_opt;
 } LEX;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 8881c79eba4..cfb12b8a5bf 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -90,7 +90,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
   bool is_fifo=0;
   LOAD_FILE_INFO lf_info;
   char * db = table_list->db ? table_list->db : thd->db;
-  bool using_transactions;
+  bool transactional_table, log_delayed;
   DBUG_ENTER("mysql_load");
 
 #ifdef EMBEDDED_LIBRARY
@@ -105,6 +105,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
   }
   if (!(table = open_ltable(thd,table_list,lock_type)))
     DBUG_RETURN(-1);
+  transactional_table= table->file->has_transactions();
+  log_delayed= (transactional_table || table->tmp_table);
+
   if (!fields.elements)
   {
     Field **field;
@@ -224,6 +227,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
     lf_info.handle_dup = handle_duplicates;
     lf_info.wrote_create_file = 0;
     lf_info.last_pos_in_file = HA_POS_ERROR;
+    lf_info.log_delayed= log_delayed;
     read_info.set_io_cache_arg((void*) &lf_info);
   }
   restore_record(table,2);
@@ -275,16 +279,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
   free_blobs(table);				/* if pack_blob was used */
   table->copy_blobs=0;
   thd->count_cuted_fields=0;			/* Don`t calc cuted fields */
-  using_transactions = table->file->has_transactions();
+
   if (error)
   {
-    if (using_transactions)
+    if (transactional_table)
       ha_autocommit_or_rollback(thd,error);
     if (!opt_old_rpl_compat && mysql_bin_log.is_open())
     {
       if (lf_info.wrote_create_file)
       {
-        Delete_file_log_event d(thd);
+        Delete_file_log_event d(thd, log_delayed);
         mysql_bin_log.write(&d);
       }
     }
@@ -297,27 +301,30 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
   if (!thd->slave_thread)
     mysql_update_log.write(thd,thd->query,thd->query_length);
 
-  if (!using_transactions)
+  if (!log_delayed)
     thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
   if (mysql_bin_log.is_open())
   {
-    if (opt_old_rpl_compat && !read_file_from_client)
+    if (opt_old_rpl_compat)
     {
-      Load_log_event qinfo(thd, ex, db, table->table_name, fields, 
-			 handle_duplicates);
-      mysql_bin_log.write(&qinfo);
+      if (!read_file_from_client)
+      {
+	Load_log_event qinfo(thd, ex, db, table->table_name, fields, 
+			     handle_duplicates, log_delayed);
+	mysql_bin_log.write(&qinfo);
+      }
     }
-    if (!opt_old_rpl_compat)
+    else
     {
       read_info.end_io_cache(); // make sure last block gets logged
       if (lf_info.wrote_create_file)
       {
-        Execute_load_log_event e(thd);
+        Execute_load_log_event e(thd, log_delayed);
         mysql_bin_log.write(&e);
       }
     }
   }
-  if (using_transactions)
+  if (transactional_table)
     error=ha_autocommit_or_rollback(thd,error); 
   DBUG_RETURN(error);
 }
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 7416506fd02..232f255da35 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2341,7 +2341,7 @@ mysql_execute_command(void)
 	mysql_update_log.write(thd, thd->query, thd->query_length);
 	if (mysql_bin_log.is_open())
 	{
-	  Query_log_event qinfo(thd, thd->query, thd->query_length);
+	  Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
 	  mysql_bin_log.write(&qinfo);
 	}
       }
@@ -2361,7 +2361,7 @@ mysql_execute_command(void)
 	mysql_update_log.write(thd, thd->query, thd->query_length);
 	if (mysql_bin_log.is_open())
 	{
-	  Query_log_event qinfo(thd, thd->query, thd->query_length);
+	  Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
 	  mysql_bin_log.write(&qinfo);
 	}
 	if (mqh_used && lex->sql_command == SQLCOM_GRANT)
@@ -2723,8 +2723,8 @@ mysql_init_query(THD *thd)
   thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE;
   thd->fatal_error=0;				// Safety
   thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
-  thd->sent_row_count=thd->examined_row_count=0;
   thd->rand_used=0;
+  thd->sent_row_count=thd->examined_row_count=0;
   thd->safe_to_cache_query=1;
   DBUG_VOID_RETURN;
 }
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 049690eb318..3eddd2646d5 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -94,7 +94,7 @@ end:
     mysql_update_log.write(thd,thd->query,thd->query_length);
     if (mysql_bin_log.is_open())
     {
-      Query_log_event qinfo(thd, thd->query, thd->query_length);
+      Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
       mysql_bin_log.write(&qinfo);
     }
     send_ok(&thd->net);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 47b258d9ed2..003bb290b41 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1132,7 +1132,8 @@ int log_loaded_block(IO_CACHE* file)
   lf_info->last_pos_in_file = file->pos_in_file;
   if (lf_info->wrote_create_file)
   {
-    Append_block_log_event a(lf_info->thd, buffer, block_len);
+    Append_block_log_event a(lf_info->thd, buffer, block_len,
+			     lf_info->log_delayed);
     mysql_bin_log.write(&a);
   }
   else
@@ -1140,7 +1141,7 @@ int log_loaded_block(IO_CACHE* file)
     Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
 			    lf_info->table_name, *lf_info->fields,
 			    lf_info->handle_dup, buffer,
-			    block_len);
+			    block_len, lf_info->log_delayed);
     mysql_bin_log.write(&c);
     lf_info->wrote_create_file = 1;
     DBUG_SYNC_POINT("debug_lock.created_file_event",10);
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 197fd03ec7c..15435382b08 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -43,13 +43,13 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg);
 typedef struct st_load_file_info
 {
   THD* thd;
+  my_off_t last_pos_in_file;
   sql_exchange* ex;
   List <Item> *fields;
   enum enum_duplicates handle_dup;
   char* db;
   char* table_name;
-  bool wrote_create_file;
-  my_off_t last_pos_in_file;
+  bool wrote_create_file, log_delayed;
 } LOAD_FILE_INFO;
 
 int log_loaded_block(IO_CACHE* file);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 865b30cdb39..36aa31e7553 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -110,6 +110,17 @@ int mysql_rm_table_part2_with_lock(THD *thd,
   return error;
 }
 
+/*
+  TODO:
+    When logging to the binary log, we should log
+    tmp_tables and transactional tables as separate statements if we
+    are in a transaction;  This is needed to get these tables into the
+    cached binary log that is only written on COMMIT.
+
+   The current code only writes DROP statements that only uses temporary
+   tables to the cache binary log.  This should be ok on most cases, but
+   not all.
+*/
 
 int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
 			 bool dont_log_query)
@@ -119,7 +130,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
   String wrong_tables;
   db_type table_type;
   int error;
-  bool some_tables_deleted=0;
+  bool some_tables_deleted=0, tmp_table_deleted=0;
   DBUG_ENTER("mysql_rm_table_part2");
 
   for (table=tables ; table ; table=table->next)
@@ -127,7 +138,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
     char *db=table->db ? table->db : thd->db;
     if (!close_temporary_table(thd, db, table->real_name))
     {
-      some_tables_deleted=1;			// Log query
+      tmp_table_deleted=1;
       continue;					// removed temporary table
     }
 
@@ -143,8 +154,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
       DBUG_RETURN(-1);
 
     /* remove form file and isam files */
-    (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table->real_name,
-		   reg_ext);
+    strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
+	    NullS);
     (void) unpack_filename(path,path);
     error=0;
 
@@ -177,7 +188,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
       wrong_tables.append(String(table->real_name));
     }
   }
-  if (some_tables_deleted)
+  if (some_tables_deleted || tmp_table_deleted)
   {
     query_cache_invalidate3(thd, tables, 0);
     if (!dont_log_query)
@@ -185,7 +196,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
       mysql_update_log.write(thd, thd->query,thd->query_length);
       if (mysql_bin_log.is_open())
       {
-	Query_log_event qinfo(thd, thd->query, thd->query_length);
+	Query_log_event qinfo(thd, thd->query, thd->query_length,
+			      tmp_table_deleted && !some_tables_deleted);
 	mysql_bin_log.write(&qinfo);
       }
     }
@@ -272,7 +284,8 @@ static int sort_keys(KEY *a, KEY *b)
     create_info		Create information (like MAX_ROWS)
     fields		List of fields to create
     keys		List of keys to create
-    tmp_table		Set to 1 if this is a temporary table
+    tmp_table		Set to 1 if this is an internal temporary table
+			(From ALTER TABLE)    
     no_log		Don't log the query to binary log.
 
   DESCRIPTION		       
@@ -690,16 +703,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
     /* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
     goto end;
   }
-  if (!tmp_table && !no_log)
-  {
-    // Must be written before unlock
-    mysql_update_log.write(thd,thd->query, thd->query_length);
-    if (mysql_bin_log.is_open())
-    {
-      Query_log_event qinfo(thd, thd->query, thd->query_length);
-      mysql_bin_log.write(&qinfo);
-    }
-  }
   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
   {
     /* Open table and put in temporary table list */
@@ -709,6 +712,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
       goto end;
     }
   }
+  if (!tmp_table && !no_log)
+  {
+    // Must be written before unlock
+    mysql_update_log.write(thd,thd->query, thd->query_length);
+    if (mysql_bin_log.is_open())
+    {
+      Query_log_event qinfo(thd, thd->query, thd->query_length,
+			    test(create_info->options &
+				 HA_LEX_CREATE_TMP_TABLE));
+      mysql_bin_log.write(&qinfo);
+    }
+  }
   error=0;
 end:
   VOID(pthread_mutex_unlock(&LOCK_open));
@@ -1408,7 +1423,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
       mysql_update_log.write(thd, thd->query, thd->query_length);
       if (mysql_bin_log.is_open())
       {
-	Query_log_event qinfo(thd, thd->query, thd->query_length);
+	Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
 	mysql_bin_log.write(&qinfo);
       }
       send_ok(&thd->net);
@@ -1773,7 +1788,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
     mysql_update_log.write(thd, thd->query,thd->query_length);
     if (mysql_bin_log.is_open())
     {
-      Query_log_event qinfo(thd, thd->query, thd->query_length);
+      Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
       mysql_bin_log.write(&qinfo);
     }
     goto end_temporary;
@@ -1902,7 +1917,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
   mysql_update_log.write(thd, thd->query,thd->query_length);
   if (mysql_bin_log.is_open())
   {
-    Query_log_event qinfo(thd, thd->query, thd->query_length);
+    Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
     mysql_bin_log.write(&qinfo);
   }
   VOID(pthread_cond_broadcast(&COND_refresh));
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 92decc63b6b..c1f02b5a30e 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -54,7 +54,7 @@ int mysql_update(THD *thd,
 		 thr_lock_type lock_type)
 {
   bool 		using_limit=limit != HA_POS_ERROR;
-  bool		used_key_is_modified, using_transactions;
+  bool		used_key_is_modified, transactional_table, log_delayed;
   int		error=0;
   uint		save_time_stamp, used_index, want_privilege;
   ulong		query_id=thd->query_id, timestamp_query_id;
@@ -301,21 +301,22 @@ int mysql_update(THD *thd,
   thd->proc_info="end";
   VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
   table->time_stamp=save_time_stamp;	// Restore auto timestamp pointer
-  using_transactions=table->file->has_transactions();
-  if (updated && (error <= 0 || !using_transactions))
+  transactional_table= table->file->has_transactions();
+  log_delayed= (transactional_table || table->tmp_table);
+  if (updated && (error <= 0 || !transactional_table))
   {
     mysql_update_log.write(thd,thd->query,thd->query_length);
     if (mysql_bin_log.is_open())
     {
       Query_log_event qinfo(thd, thd->query, thd->query_length,
-			    using_transactions);
-      if (mysql_bin_log.write(&qinfo) && using_transactions)
-	error=1;
+			    log_delayed);
+      if (mysql_bin_log.write(&qinfo) && transactional_table)
+	error=1;				// Rollback update
     }
-    if (!using_transactions)
+    if (!log_delayed)
       thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
   }
-  if (using_transactions && ha_autocommit_or_rollback(thd, error >= 0))
+  if (transactional_table && ha_autocommit_or_rollback(thd, error >= 0))
     error=1;
   if (updated)
   {
@@ -790,7 +791,7 @@ bool multi_update::send_eof()
   if (updated || not_trans_safe)
   {
     mysql_update_log.write(thd,thd->query,thd->query_length);
-    Query_log_event qinfo(thd, thd->query, thd->query_length);
+    Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
 
     /*
       mysql_bin_log is not open if binlogging or replication
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index b4d1fa802bb..911fc12d9c4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -513,6 +513,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
 	type int_type real_type order_dir opt_field_spec lock_option
 	udf_type if_exists opt_local opt_table_options table_options
 	table_option opt_if_not_exists opt_var_type opt_var_ident_type
+	opt_temporary
 
 %type <ulong_num>
 	ULONG_NUM raid_types merge_insert_types
@@ -2383,11 +2384,12 @@ do:	DO_SYM
 */
 
 drop:
-	DROP TABLE_SYM if_exists table_list opt_restrict
+	DROP opt_temporary TABLE_SYM if_exists table_list opt_restrict
 	{
 	  LEX *lex=Lex;
 	  lex->sql_command = SQLCOM_DROP_TABLE;
-	  lex->drop_if_exists = $3;
+	  lex->drop_temporary= $2;
+	  lex->drop_if_exists= $4;
 	}
 	| DROP INDEX ident ON table_ident {}
 	  {
@@ -2424,8 +2426,13 @@ table_name:
 
 if_exists:
 	/* empty */ { $$=0; }
-	| IF EXISTS { $$= 1; };
+	| IF EXISTS { $$= 1; }
+	;
 
+opt_temporary:
+	/* empty */ { $$= 0; }
+	| TEMPORARY { $$= 1; }
+	;
 /*
 ** Insert : add new data to table
 */
diff --git a/sql/table.cc b/sql/table.cc
index d3b719c553d..b68edac5fc2 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -47,19 +47,19 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
   int	 j,error;
   uint	 rec_buff_length,n_length,int_length,records,key_parts,keys,
          interval_count,interval_parts,read_length,db_create_options;
-  uint	 key_info_length;
+  uint	 key_info_length, com_length;
   ulong  pos;
-  char	 index_file[FN_REFLEN], *names,*keynames;
+  char	 index_file[FN_REFLEN], *names, *keynames;
   uchar  head[288],*disk_buff,new_field_pack_flag;
   my_string record;
   const char **int_array;
-  bool	 new_frm_ver,use_hash, null_field_first;
+  bool	 use_hash, null_field_first;
   File	 file;
   Field  **field_ptr,*reg_field;
   KEY	 *keyinfo;
   KEY_PART_INFO *key_part;
   uchar *null_pos;
-  uint null_bit;
+  uint null_bit, new_frm_ver, field_pack_length;
   SQL_CRYPT *crypted=0;
   DBUG_ENTER("openfrm");
   DBUG_PRINT("enter",("name: '%s'  form: %lx",name,outparam));
@@ -95,14 +95,15 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
 
   if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
   if (head[0] != (uchar) 254 || head[1] != 1 ||
-      (head[2] != FRM_VER && head[2] != FRM_VER+1))
-    goto err_not_open; /* purecov: inspected */
+      (head[2] != FRM_VER && head[2] > FRM_VER+2))
+    goto err_not_open;				/* purecov: inspected */
   new_field_pack_flag=head[27];
-  new_frm_ver= (head[2] == FRM_VER+1);
+  new_frm_ver= (head[2] - FRM_VER);
+  field_pack_length= new_frm_ver < 2 ? 11 : 15;
 
   error=3;
   if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
-    goto err_not_open; /* purecov: inspected */
+    goto err_not_open;				/* purecov: inspected */
   *fn_ext(index_file)='\0';			// Remove .frm extension
 
   outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3));
@@ -153,9 +154,23 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
 
   for (i=0 ; i < keys ; i++, keyinfo++)
   {
-    keyinfo->flags=	 ((uint) strpos[0]) ^ HA_NOSAME;
-    keyinfo->key_length= (uint) uint2korr(strpos+1);
-    keyinfo->key_parts=  (uint) strpos[3];  strpos+=4;
+    if (new_frm_ver == 2)
+    {
+      keyinfo->flags=	   (uint) uint2korr(strpos) ^ HA_NOSAME;
+      keyinfo->key_length= (uint) uint2korr(strpos+2);
+      keyinfo->key_parts=  (uint) strpos[4];
+      keyinfo->algorithm=  (enum ha_key_alg) strpos[5];
+      strpos+=8;
+    }
+    else
+    {
+      keyinfo->flags=	 ((uint) strpos[0]) ^ HA_NOSAME;
+      keyinfo->key_length= (uint) uint2korr(strpos+1);
+      keyinfo->key_parts=  (uint) strpos[3];
+      keyinfo->algorithm= HA_KEY_ALG_UNDEF;
+      strpos+=4;
+    }
+
     keyinfo->key_part=	 key_part;
     keyinfo->rec_per_key= rec_per_key;
     for (j=keyinfo->key_parts ; j-- ; key_part++)
@@ -165,7 +180,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
       key_part->offset= (uint) uint2korr(strpos+2)-1;
       key_part->key_type=	(uint) uint2korr(strpos+5);
       // key_part->field=	(Field*) 0;	// Will be fixed later
-      if (new_frm_ver)
+      if (new_frm_ver >= 1)
       {
 	key_part->key_part_flag= *(strpos+4);
 	key_part->length=	(uint) uint2korr(strpos+7);
@@ -191,14 +206,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
   }
   keynames=(char*) key_part;
   strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
-  /* Test if new 4.0 format */
-  if ((uint) (strpos - disk_buff) < key_info_length)
-  {
-    /* Read key types */
-    keyinfo=outparam->key_info;
-    for (i=0 ; i < keys ; i++, keyinfo++)
-      keyinfo->algorithm= (enum ha_key_alg) *(strpos++);
-  }
 
   outparam->reclength = uint2korr((head+16));
   if (*(head+26) == 1)
@@ -267,6 +274,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
   interval_parts=uint2korr(head+272);
   int_length=uint2korr(head+274);
   outparam->null_fields=uint2korr(head+282);
+  com_length=uint2korr(head+284);
   outparam->comment=strdup_root(&outparam->mem_root,
 				(char*) head+47);
 
@@ -278,12 +286,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
 			   interval_count*sizeof(TYPELIB)+
 			   (outparam->fields+interval_parts+
 			    keys+3)*sizeof(my_string)+
-			   (n_length+int_length)))))
+			   (n_length+int_length+com_length)))))
     goto err_not_open; /* purecov: inspected */
 
   outparam->field=field_ptr;
-  read_length=((uint) (outparam->fields*11)+pos+
-	       (uint) (n_length+int_length));
+  read_length=(uint) (outparam->fields * field_pack_length +
+		      pos+ (uint) (n_length+int_length+com_length));
   if (read_string(file,(gptr*) &disk_buff,read_length))
     goto err_not_open; /* purecov: inspected */
   if (crypted)
@@ -299,7 +307,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
   names= (char*) (int_array+outparam->fields+interval_parts+keys+3);
   if (!interval_count)
     outparam->intervals=0;			// For better debugging
-  memcpy((char*) names, strpos+(outparam->fields*11),
+  memcpy((char*) names, strpos+(outparam->fields*field_pack_length),
 	 (uint) (n_length+int_length));
 
   fix_type_pointers(&int_array,&outparam->fieldnames,1,&names);
@@ -332,22 +340,40 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
 			 (hash_get_key) get_field_name,0,
 			 HASH_CASE_INSENSITIVE);
 
-  for (i=0 ; i < outparam->fields; i++, strpos+= 11, field_ptr++)
+  for (i=0 ; i < outparam->fields; i++, strpos+=field_pack_length, field_ptr++)
   {
     uint pack_flag= uint2korr(strpos+6);
     uint interval_nr= (uint) strpos[10];
+    enum_field_types field_type;
+
+    if (new_frm_ver == 2)
+    {
+      /* new frm file in 4.1 */
+      field_type=(enum_field_types) (uint) strpos[11];
+    }
+    else
+    {
+      /* old frm file */
+      field_type= (enum_field_types) f_packtype(pack_flag);
+    }
 
     *field_ptr=reg_field=
       make_field(record+uint2korr(strpos+4),
 		 (uint32) strpos[3],		// field_length
 		 null_pos,null_bit,
 		 pack_flag,
+		 field_type,
 		 (Field::utype) MTYP_TYPENR((uint) strpos[8]),
 		 (interval_nr ?
 		  outparam->intervals+interval_nr-1 :
 		  (TYPELIB*) 0),
 		 outparam->fieldnames.type_names[i],
 		 outparam);
+    if (!*field_ptr)				// Field in 4.1
+    {
+      error= 4;
+      goto err_not_open;			/* purecov: inspected */
+    }
     if (!(reg_field->flags & NOT_NULL_FLAG))
     {
       if ((null_bit<<=1) == 256)
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 7d0201f75ae..cc8440da1e4 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -557,6 +557,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
 			       null_pos+null_count/8,
 			       1 << (null_count & 7),
 			       field->pack_flag,
+			       field->sql_type,
 			       field->unireg_check,
 			       field->interval,
 			       field->field_name,