List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:July 31 2008 10:32pm
Subject:bzr commit into mysql-6.0-runtime branch (davi:2690) WL#4284
View as plain text  
# At a local mysql-6.0-runtime repository of davi

 2690 Davi Arnaut	2008-07-31
      WL#4284: Transactional DDL locking
      
      Make transaction management more modular through a new interface.
      
      The overall objective of this change is to provide groundwork
      for the design of transactional DDL locking by cleaning up the
      transaction high level API to better distinguish operations implicit
      and explicit, and single statement transaction from operations on
      the normal transaction.
      
      Having a a high-level interface for transaction management provides
      a better base for implementing transactional concepts that are not
      always tied to storage engines and also makes it easier to interect
      with other higher level modules of the server.
added:
  sql/transaction.cc
  sql/transaction.h
modified:
  client/Makefile.am
  libmysqld/CMakeLists.txt
  libmysqld/Makefile.am
  sql/CMakeLists.txt
  sql/Makefile.am
  sql/backup/be_snapshot.cc
  sql/backup/kernel.cc
  sql/handler.cc
  sql/handler.h
  sql/lock.cc
  sql/log_event.cc
  sql/log_event_old.cc
  sql/mysql_priv.h
  sql/rpl_injector.cc
  sql/rpl_rli.cc
  sql/set_var.cc
  sql/slave.cc
  sql/sql_base.cc
  sql/sql_class.cc
  sql/sql_do.cc
  sql/sql_insert.cc
  sql/sql_parse.cc
  sql/sql_partition.cc
  sql/sql_table.cc
  sql/sql_yacc.yy
  storage/maria/ha_maria.cc

per-file messages:
  client/Makefile.am
    Add new file to the build.
  libmysqld/CMakeLists.txt
    Add new file to the build.
  libmysqld/Makefile.am
    Add new file to the build.
  sql/CMakeLists.txt
    Add new file to the build.
  sql/Makefile.am
    Add new file to the build.
  sql/backup/be_snapshot.cc
    Rename transaction management functions to the new names.
  sql/backup/kernel.cc
    Rename transaction management functions to the new names.
  sql/handler.cc
    Remove multiplexer commit or rollback function. Most callers already
    have enough information to decided whether to rollback or commit.
    Having plain and well named functions makes it easier to read
    and understand code.
  sql/handler.h
    Remove wrapper function as the low level transaction functions
    shouldn't be called directly anymore.
  sql/lock.cc
    Rename transaction management functions to the new names.
  sql/log_event.cc
    Rename transaction management functions to the new names.
  sql/log_event_old.cc
    Rename transaction management functions to the new names.
  sql/mysql_priv.h
    Remove obsolete functions for implicit and explicit commit.
  sql/rpl_injector.cc
    Rename transaction management functions to the new names.
  sql/rpl_rli.cc
    Rename transaction management functions to the new names.
  sql/set_var.cc
    Rename transaction management functions to the new names.
  sql/slave.cc
    Rename transaction management functions to the new names.
  sql/sql_base.cc
    Rename transaction management functions to the new names.
  sql/sql_class.cc
    Rename transaction management functions to the new names.
  sql/sql_do.cc
    Rename transaction management functions to the new names.
  sql/sql_insert.cc
    Rename transaction management functions to the new names.
  sql/sql_parse.cc
    Move transaction management functions to it's own file.
  sql/sql_partition.cc
    Rename transaction management functions to the new names.
  sql/sql_table.cc
    Rename transaction management functions to the new names.
  sql/sql_yacc.yy
    Add header as function indirectly calls transaction functions.
  sql/transaction.cc
    Implement wrapper functions to differentiate operations on
    the single statement transaction from the ones operating
    on the normal transaction.
  sql/transaction.h
    Export new functions for dealing with transaction commands.
  storage/maria/ha_maria.cc
    Rename transaction management functions to the new names.
=== modified file 'client/Makefile.am'
--- a/client/Makefile.am	2008-06-20 11:40:01 +0000
+++ b/client/Makefile.am	2008-07-31 20:31:54 +0000
@@ -105,7 +105,8 @@ DEFS =			-DUNDEF_THREADS_HACK \
 sql_src=log_event.h mysql_priv.h rpl_constants.h \
 	log_event.cc my_decimal.h my_decimal.cc \
 	log_event_old.h log_event_old.cc \
-	rpl_record_old.h rpl_record_old.cc
+	rpl_record_old.h rpl_record_old.cc \
+	transaction.h
 strings_src=decimal.c dtoa.c
 
 link_sources:

=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt	2008-07-09 07:12:43 +0000
+++ b/libmysqld/CMakeLists.txt	2008-07-31 20:31:54 +0000
@@ -203,6 +203,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libm
            ../sql/scheduler.cc ../sql/sql_audit.cc
            ../sql/ddl_blocker.cc ../sql/si_objects.cc
            ../sql/event_parse_data.cc ../sql/mdl.cc
+           ../sql/transaction.cc
            ${GEN_SOURCES}
            ${LIB_SOURCES})
 

=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am	2008-07-09 07:12:43 +0000
+++ b/libmysqld/Makefile.am	2008-07-31 20:31:54 +0000
@@ -78,8 +78,7 @@ sqlsources = derror.cc field.cc field_co
 	sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
 	parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
 	rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
-	debug_sync.cc \
-	sql_tablespace.cc \
+	debug_sync.cc sql_tablespace.cc transaction.cc \
 	rpl_injector.cc my_user.c partition_info.cc \
 	sql_servers.cc ddl_blocker.cc si_objects.cc sql_audit.cc \
         event_parse_data.cc mdl.cc

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2008-07-09 07:12:43 +0000
+++ b/sql/CMakeLists.txt	2008-07-31 20:31:54 +0000
@@ -75,7 +75,7 @@ ADD_EXECUTABLE(mysqld
                sql_tablespace.cc events.cc ../sql-common/my_user.c 
                partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
                rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc
-               sql_connect.cc scheduler.cc 
+               sql_connect.cc scheduler.cc transaction.cc
                ddl_blocker.cc si_objects.cc
                sql_profile.cc event_parse_data.cc mdl.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2008-07-09 07:12:43 +0000
+++ b/sql/Makefile.am	2008-07-31 20:31:54 +0000
@@ -87,7 +87,7 @@ noinst_HEADERS =	item.h item_func.h item
 			sql_plugin.h authors.h event_parse_data.h \
 			event_data_objects.h event_scheduler.h \
 			sql_partition.h partition_info.h partition_element.h \
-			probes.h sql_audit.h \
+			probes.h sql_audit.h transaction.h \
 			contributors.h sql_servers.h ddl_blocker.h \
 			si_objects.h sql_plist.h mdl.h
 
@@ -136,7 +136,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			sql_builtin.cc sql_tablespace.cc partition_info.cc \
 			sql_servers.cc sql_audit.cc sha2.cc \
 			ddl_blocker.cc si_objects.cc event_parse_data.cc \
-			mdl.cc
+			mdl.cc transaction.cc
 
 if HAVE_DTRACE
   mysqld_SOURCES += probes.d

=== modified file 'sql/backup/be_snapshot.cc'
--- a/sql/backup/be_snapshot.cc	2008-07-07 12:51:56 +0000
+++ b/sql/backup/be_snapshot.cc	2008-07-31 20:31:54 +0000
@@ -44,6 +44,7 @@
 #include "backup_engine.h"
 #include "be_snapshot.h"
 #include "backup_aux.h"
+#include "transaction.h"
 
 namespace snapshot_backup {
 
@@ -72,8 +73,8 @@ result_t Backup::cleanup()
     locking_thd->lock_state= LOCK_DONE; // set lock done so destructor won't wait
     if (m_trans_start)
     {
-      ha_autocommit_or_rollback(locking_thd->m_thd, 0);
-      end_active_trans(locking_thd->m_thd);
+      trans_commit_stmt(locking_thd->m_thd);
+      trans_commit_implicit(locking_thd->m_thd);
       m_trans_start= FALSE;
     }
     if (tables_open)
@@ -104,7 +105,7 @@ result_t Backup::lock()
   locking_thd->m_thd->lex->sql_command= SQLCOM_SELECT; 
   locking_thd->m_thd->lex->start_transaction_opt|=
     MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
-  int res= begin_trans(locking_thd->m_thd);
+  int res= trans_begin(locking_thd->m_thd);
   if (res)
     DBUG_RETURN(ERROR);
   m_trans_start= TRUE;

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-07-19 03:03:39 +0000
+++ b/sql/backup/kernel.cc	2008-07-31 20:31:54 +0000
@@ -75,6 +75,7 @@
 #include "be_nodata.h"
 #include "ddl_blocker.h"
 #include "backup_progress.h"
+#include "transaction.h"
 
 
 /** 
@@ -737,8 +738,8 @@ int Backup_restore_ctx::close()
 
   if (m_thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
   {
-    ha_autocommit_or_rollback(m_thd, 0);
-    end_active_trans(m_thd);
+    trans_commit_stmt(m_thd);
+    trans_commit_implicit(m_thd);
   }
 
   // unlock tables if they are still locked

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2008-07-25 17:21:55 +0000
+++ b/sql/handler.cc	2008-07-31 20:31:54 +0000
@@ -27,6 +27,7 @@
 #include "rpl_filter.h"
 #include <myisampack.h>
 #include "myisam.h"
+#include "transaction.h"
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 #include "ha_partition.h"
@@ -836,7 +837,7 @@ void ha_close_connection(THD* thd)
   do not "register" in thd->transaction lists, and thus do not
   modify the transaction state. Besides, each DDL in
   MySQL is prefixed with an implicit normal transaction commit
-  (a call to end_active_trans()), and thus leaves nothing
+  (a call to trans_commit_implicit()), and thus leaves nothing
   to modify.
   However, as it has been pointed out with CREATE TABLE .. SELECT,
   some DDL statements can start a *new* transaction.
@@ -1277,42 +1278,6 @@ int ha_rollback_trans(THD *thd, bool all
   DBUG_RETURN(error);
 }
 
-/**
-  This is used to commit or rollback a single statement depending on
-  the value of error.
-
-  @note
-    Note that if the autocommit is on, then the following call inside
-    InnoDB will commit or rollback the whole transaction (= the statement). The
-    autocommit mechanism built into InnoDB is based on counting locks, but if
-    the user has used LOCK TABLES then that mechanism does not know to do the
-    commit.
-*/
-int ha_autocommit_or_rollback(THD *thd, int error)
-{
-  DBUG_ENTER("ha_autocommit_or_rollback");
-
-  if (thd->transaction.stmt.ha_list)
-  {
-    if (!error)
-    {
-      if (ha_commit_trans(thd, 0))
-	error=1;
-    }
-    else 
-    {
-      (void) ha_rollback_trans(thd, 0);
-      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
-        (void) ha_rollback(thd);
-    }
-
-    thd->variables.tx_isolation=thd->session_tx_isolation;
-  }
-
-  DBUG_RETURN(error);
-}
-
-
 struct xahton_st {
   XID *xid;
   int result;
@@ -3377,7 +3342,7 @@ int ha_enable_transaction(THD *thd, bool
       So, let's commit an open transaction (if any) now.
     */
     if (!(error= ha_commit_trans(thd, 0)))
-      error= end_trans(thd, COMMIT);
+      error= trans_commit_implicit(thd);
   }
   DBUG_RETURN(error);
 }

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2008-07-11 16:22:44 +0000
+++ b/sql/handler.h	2008-07-31 20:31:54 +0000
@@ -289,9 +289,6 @@ typedef Bitmap<HA_MAX_ALTER_FLAGS> HA_AL
 #define HA_CACHE_TBL_ASKTRANSACT 2
 #define HA_CACHE_TBL_TRANSACT    4
 
-/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
-#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
-
 /* Flags for method is_fatal_error */
 #define HA_CHECK_DUP_KEY 1
 #define HA_CHECK_DUP_UNIQUE 2
@@ -2403,10 +2400,6 @@ extern TYPELIB tx_isolation_typelib;
 extern TYPELIB myisam_stats_method_typelib;
 extern ulong total_ha, total_ha_2pc;
 
-       /* Wrapper functions */
-#define ha_commit(thd) (ha_commit_trans((thd), TRUE))
-#define ha_rollback(thd) (ha_rollback_trans((thd), TRUE))
-
 /* lookups */
 handlerton *ha_default_handlerton(THD *thd);
 plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name);
@@ -2483,13 +2476,12 @@ int ha_release_temporary_latches(THD *th
 int ha_start_consistent_snapshot(THD *thd);
 int ha_commit_or_rollback_by_xid(XID *xid, bool commit);
 int ha_commit_one_phase(THD *thd, bool all);
+int ha_commit_trans(THD *thd, bool all);
 int ha_rollback_trans(THD *thd, bool all);
 int ha_prepare(THD *thd);
 int ha_recover(HASH *commit_list);
 
 /* transactions: these functions never call handlerton functions directly */
-int ha_commit_trans(THD *thd, bool all);
-int ha_autocommit_or_rollback(THD *thd, int error);
 int ha_enable_transaction(THD *thd, bool on);
 
 /* savepoints */

=== modified file 'sql/lock.cc'
--- a/sql/lock.cc	2008-07-09 07:12:43 +0000
+++ b/sql/lock.cc	2008-07-31 20:31:54 +0000
@@ -74,6 +74,7 @@
 */
 
 #include "mysql_priv.h"
+#include "transaction.h"
 #include <hash.h>
 #include <assert.h>
 
@@ -1440,7 +1441,7 @@ int try_transactional_lock(THD *thd, TAB
 
  err:
   /* We need to explicitly commit if autocommit mode is active. */
-  (void) ha_autocommit_or_rollback(thd, 0);
+  trans_commit_stmt(thd);
   /* Close the tables. The locks (if taken) persist in the storage engines. */
   close_tables_for_reopen(thd, &table_list, FALSE);
   thd->in_lock_tables= FALSE;

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2008-07-24 10:00:56 +0000
+++ b/sql/log_event.cc	2008-07-31 20:31:54 +0000
@@ -31,6 +31,7 @@
 #include "rpl_filter.h"
 #include "rpl_utility.h"
 #include "rpl_record.h"
+#include "transaction.h"
 #include <my_dir.h>
 
 #endif /* MYSQL_CLIENT */
@@ -4506,7 +4507,7 @@ int Xid_log_event::do_apply_event(Relay_
   /* For a slave Xid_log_event is COMMIT */
   general_log_print(thd, COM_QUERY,
                     "COMMIT /* implicit, from Xid_log_event */");
-  return end_trans(thd, COMMIT);
+  return trans_commit(thd);
 }
 
 Log_event::enum_skip_reason
@@ -6830,7 +6831,7 @@ Rows_log_event::do_update_pos(Relay_log_
       are involved, commit the transaction and flush the pending event to the
       binlog.
     */
-    error= ha_autocommit_or_rollback(thd, 0);
+    error= trans_commit_stmt(thd);
 
     /*
       Now what if this is not a transactional engine? we still need to

=== modified file 'sql/log_event_old.cc'
--- a/sql/log_event_old.cc	2008-06-28 11:00:59 +0000
+++ b/sql/log_event_old.cc	2008-07-31 20:31:54 +0000
@@ -6,6 +6,7 @@
 #endif
 #include "log_event_old.h"
 #include "rpl_record_old.h"
+#include "transaction.h"
 
 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
 
@@ -1827,7 +1828,7 @@ Old_rows_log_event::do_update_pos(Relay_
       are involved, commit the transaction and flush the pending event to the
       binlog.
     */
-    error= ha_autocommit_or_rollback(thd, 0);
+    error= trans_commit_stmt(thd);
 
     /*
       Now what if this is not a transactional engine? we still need to

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2008-07-26 16:38:20 +0000
+++ b/sql/mysql_priv.h	2008-07-31 20:31:54 +0000
@@ -889,15 +889,6 @@ bool parse_sql(THD *thd,
                Parser_state *parser_state,
                Object_creation_ctx *creation_ctx);
 
-enum enum_mysql_completiontype {
-  ROLLBACK_RELEASE=-2, ROLLBACK=1,  ROLLBACK_AND_CHAIN=7,
-  COMMIT_RELEASE=-1,   COMMIT=0,    COMMIT_AND_CHAIN=6
-};
-
-bool begin_trans(THD *thd);
-bool end_active_trans(THD *thd);
-int end_trans(THD *thd, enum enum_mysql_completiontype completion);
-
 Item *negate_expression(THD *thd, Item *expr);
 
 /* log.cc */

=== modified file 'sql/rpl_injector.cc'
--- a/sql/rpl_injector.cc	2008-05-29 15:44:11 +0000
+++ b/sql/rpl_injector.cc	2008-07-31 20:31:54 +0000
@@ -15,6 +15,7 @@
 
 #include "mysql_priv.h" 
 #include "rpl_injector.h"
+#include "transaction.h"
 
 /*
   injector::transaction - member definitions
@@ -36,7 +37,7 @@ injector::transaction::transaction(MYSQL
   m_start_pos.m_file_pos= log_info.pos;
 
   m_thd->lex->start_transaction_opt= 0; /* for begin_trans() */
-  begin_trans(m_thd);
+  trans_begin(m_thd);
 
   thd->set_current_stmt_binlog_row_based();
 }
@@ -82,8 +83,8 @@ int injector::transaction::commit()
      is committed by committing the statement transaction
      explicitly.
    */
-   ha_autocommit_or_rollback(m_thd, 0);
-   end_trans(m_thd, COMMIT);
+   trans_commit_stmt(m_thd);
+   trans_commit(m_thd);
    DBUG_RETURN(0);
 }
 

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2008-06-28 11:00:59 +0000
+++ b/sql/rpl_rli.cc	2008-07-31 20:31:54 +0000
@@ -20,6 +20,7 @@
 #include <my_dir.h>    // For MY_STAT
 #include "sql_repl.h"  // For check_binlog_magic
 #include "rpl_utility.h"
+#include "transaction.h"
 
 static int count_relay_log_space(Relay_log_info* rli);
 
@@ -1162,8 +1163,8 @@ void Relay_log_info::cleanup_context(THD
   */
   if (error)
   {
-    ha_autocommit_or_rollback(thd, 1); // if a "statement transaction"
-    end_trans(thd, ROLLBACK); // if a "real transaction"
+    trans_rollback_stmt(thd); // if a "statement transaction"
+    trans_rollback(thd);      // if a "real transaction"
   }
   m_table_map.clear_tables();
   slave_close_thread_tables(thd);

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2008-07-25 17:21:55 +0000
+++ b/sql/set_var.cc	2008-07-31 20:31:54 +0000
@@ -61,6 +61,7 @@
 #include <my_dir.h>
 
 #include "events.h"
+#include "transaction.h"
 
 /* WITH_NDBCLUSTER_STORAGE_ENGINE */
 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
@@ -2979,7 +2980,7 @@ static bool set_option_autocommit(THD *t
    */
   if (var->save_result.ulong_value != 0 &&
       (thd->options & OPTION_NOT_AUTOCOMMIT) &&
-      ha_commit(thd))
+      trans_commit(thd))
     return 1;
 
   if (var->save_result.ulong_value != 0)

=== modified file 'sql/slave.cc'
--- a/sql/slave.cc	2008-07-21 03:55:09 +0000
+++ b/sql/slave.cc	2008-07-31 20:31:54 +0000
@@ -34,6 +34,7 @@
 #include "sql_repl.h"
 #include "rpl_filter.h"
 #include "repl_failsafe.h"
+#include "transaction.h"
 #include <thr_alarm.h>
 #include <my_dir.h>
 #include <sql_common.h>
@@ -1953,7 +1954,7 @@ static int exec_relay_log_event(THD* thd
           else
           {
             exec_res= 0;
-            end_trans(thd, ROLLBACK);
+            trans_rollback(thd);
             /* chance for concurrent connection to get more locks */
             safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
                        (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli);

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2008-07-09 14:27:18 +0000
+++ b/sql/sql_base.cc	2008-07-31 20:31:54 +0000
@@ -21,6 +21,7 @@
 #include "sp_head.h"
 #include "sp.h"
 #include "sql_trigger.h"
+#include "transaction.h"
 #include <m_ctype.h>
 #include <my_dir.h>
 #include <hash.h>
@@ -1355,7 +1356,7 @@ void close_thread_tables(THD *thd,
   if (!(thd->state_flags & Open_tables_state::BACKUPS_AVAIL))
   {
     thd->main_da.can_overwrite_status= TRUE;
-    ha_autocommit_or_rollback(thd, thd->is_error());
+    thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
     thd->main_da.can_overwrite_status= FALSE;
 
     /*

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2008-07-25 17:21:55 +0000
+++ b/sql/sql_class.cc	2008-07-31 20:31:54 +0000
@@ -42,6 +42,7 @@
 
 #include "sp_rcontext.h"
 #include "sp_cache.h"
+#include "transaction.h"
 
 /*
   The following is used to initialise Table_ident with a internal
@@ -846,7 +847,8 @@ void THD::cleanup(void)
   }
 #endif
   {
-    ha_rollback(this);
+    transaction.xid_state.xa_state= XA_NOTR;
+    trans_rollback(this);
     xid_cache_delete(&transaction.xid_state);
   }
   locked_tables_list.unlock_locked_tables(this);

=== modified file 'sql/sql_do.cc'
--- a/sql/sql_do.cc	2008-02-19 12:45:21 +0000
+++ b/sql/sql_do.cc	2008-07-31 20:31:54 +0000
@@ -17,6 +17,7 @@
 /* Execute DO statement */
 
 #include "mysql_priv.h"
+#include "transaction.h"
 
 bool mysql_do(THD *thd, List<Item> &values)
 {
@@ -36,7 +37,7 @@ bool mysql_do(THD *thd, List<Item> &valu
       will clear the error and the rollback in the end of
       dispatch_command() won't work.
     */
-    ha_autocommit_or_rollback(thd, thd->is_error());
+    trans_rollback_stmt(thd);
     thd->clear_error(); // DO always is OK
   }
   my_ok(thd);

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2008-07-21 03:55:09 +0000
+++ b/sql/sql_insert.cc	2008-07-31 20:31:54 +0000
@@ -62,6 +62,7 @@
 #include "slave.h"
 #include "rpl_mi.h"
 #include "sql_audit.h"
+#include "transaction.h"
 
 #ifndef EMBEDDED_LIBRARY
 static bool delayed_get_table(THD *thd, TABLE_LIST *table_list);
@@ -2487,7 +2488,7 @@ pthread_handler_t handle_delayed_insert(
       */
       di->table->file->ha_release_auto_increment();
       mysql_unlock_tables(thd, lock);
-      ha_autocommit_or_rollback(thd, 0);
+      trans_commit_stmt(thd);
       di->group_count=0;
       mysql_audit_release(thd);
       pthread_mutex_lock(&di->mutex);
@@ -2508,7 +2509,7 @@ err:
     first call to ha_*_row() instead. Remove code that are used to
     cover for the case outlined above.
    */
-  ha_autocommit_or_rollback(thd, 1);
+  trans_rollback_stmt(thd);
 
 #ifndef __WIN__
 end:
@@ -3746,8 +3747,8 @@ bool select_create::send_eof()
     */
     if (!table->s->tmp_table)
     {
-      ha_autocommit_or_rollback(thd, 0);
-      end_active_trans(thd);
+      trans_commit_stmt(thd);
+      trans_commit_implicit(thd);
     }
 
     table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2008-07-26 16:38:20 +0000
+++ b/sql/sql_parse.cc	2008-07-31 20:31:54 +0000
@@ -29,6 +29,7 @@
 #include "sql_trigger.h"
 #include <ddl_blocker.h>
 #include "sql_audit.h"
+#include "transaction.h"
 
 #ifdef BACKUP_TEST
 #include "backup/backup_test.h"
@@ -97,65 +98,6 @@ const char *xa_state_names[]={
 
 extern DDL_blocker_class *DDL_blocker;
 
-bool end_active_trans(THD *thd)
-{
-  int error=0;
-  DBUG_ENTER("end_active_trans");
-  if (unlikely(thd->in_sub_stmt))
-  {
-    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-    DBUG_RETURN(1);
-  }
-  if (thd->transaction.xid_state.xa_state != XA_NOTR)
-  {
-    my_error(ER_XAER_RMFAIL, MYF(0),
-             xa_state_names[thd->transaction.xid_state.xa_state]);
-    DBUG_RETURN(1);
-  }
-  if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
-		      OPTION_TABLE_LOCK))
-  {
-    DBUG_PRINT("info",("options: 0x%llx", thd->options));
-    /* Safety if one did "drop table" on locked tables */
-    if (!thd->locked_tables_mode)
-      thd->options&= ~OPTION_TABLE_LOCK;
-    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
-    if (ha_commit(thd))
-      error=1;
-#ifdef WITH_MARIA_STORAGE_ENGINE
-    ha_maria::implicit_commit(thd, TRUE);
-#endif
-  }
-  thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
-  thd->transaction.all.modified_non_trans_table= FALSE;
-  DBUG_RETURN(error);
-}
-
-
-bool begin_trans(THD *thd)
-{
-  int error=0;
-  if (unlikely(thd->in_sub_stmt))
-  {
-    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-    return 1;
-  }
-
-  thd->locked_tables_list.unlock_locked_tables(thd);
-
-  if (end_active_trans(thd))
-    error= -1;
-  else
-  {
-    LEX *lex= thd->lex;
-    thd->options|= OPTION_BEGIN;
-    thd->server_status|= SERVER_STATUS_IN_TRANS;
-    if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
-      error= ha_start_consistent_snapshot(thd);
-  }
-  return error;
-}
-
 #ifdef HAVE_REPLICATION
 /**
   Returns true if all tables should be ignored.
@@ -216,9 +158,9 @@ static bool opt_implicit_commit(THD *thd
   if (!skip)
   {
     /* Commit or rollback the statement transaction. */
-    ha_autocommit_or_rollback(thd, thd->is_error());
+    thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
     /* Commit the normal transaction if one is active. */
-    res= end_active_trans(thd);
+    res= trans_commit_implicit(thd);
   }
 
   DBUG_RETURN(res);
@@ -629,81 +571,6 @@ void cleanup_items(Item *item)
   DBUG_VOID_RETURN;
 }
 
-/**
-  Ends the current transaction and (maybe) begin the next.
-
-  @param thd            Current thread
-  @param completion     Completion type
-
-  @retval
-    0   OK
-*/
-
-int end_trans(THD *thd, enum enum_mysql_completiontype completion)
-{
-  bool do_release= 0;
-  int res= 0;
-  DBUG_ENTER("end_trans");
-
-  if (unlikely(thd->in_sub_stmt))
-  {
-    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-    DBUG_RETURN(1);
-  }
-  if (thd->transaction.xid_state.xa_state != XA_NOTR)
-  {
-    my_error(ER_XAER_RMFAIL, MYF(0),
-             xa_state_names[thd->transaction.xid_state.xa_state]);
-    DBUG_RETURN(1);
-  }
-  thd->lex->start_transaction_opt= 0; /* for begin_trans() */
-  switch (completion) {
-  case COMMIT:
-    /*
-     We don't use end_active_trans() here to ensure that this works
-     even if there is a problem with the OPTION_AUTO_COMMIT flag
-     (Which of course should never happen...)
-    */
-    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
-    res= ha_commit(thd);
-    thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
-    thd->transaction.all.modified_non_trans_table= FALSE;
-    break;
-  case COMMIT_RELEASE:
-    do_release= 1; /* fall through */
-  case COMMIT_AND_CHAIN:
-    res= end_active_trans(thd);
-    if (!res && completion == COMMIT_AND_CHAIN)
-      res= begin_trans(thd);
-    break;
-  case ROLLBACK_RELEASE:
-    do_release= 1; /* fall through */
-  case ROLLBACK:
-  case ROLLBACK_AND_CHAIN:
-  {
-    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
-    if (ha_rollback(thd))
-      res= -1;
-    thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
-    thd->transaction.all.modified_non_trans_table= FALSE;
-    if (!res && (completion == ROLLBACK_AND_CHAIN))
-      res= begin_trans(thd);
-    break;
-  }
-  default:
-    res= -1;
-    my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
-    DBUG_RETURN(-1);
-  }
-
-  if (res < 0)
-    my_error(thd->killed_errno(), MYF(0));
-  else if ((res == 0) && do_release)
-    thd->killed= THD::KILL_CONNECTION;
-
-  DBUG_RETURN(res);
-}
-
 #ifndef EMBEDDED_LIBRARY
 
 /**
@@ -1326,14 +1193,14 @@ bool dispatch_command(enum enum_server_c
     bool not_used;
     status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
     ulong options= (ulong) (uchar) packet[0];
-    if (end_active_trans(thd))
+    if (trans_commit_implicit(thd))
       break;
     if (check_global_access(thd,RELOAD_ACL))
       break;
     general_log_print(thd, command, NullS);
     if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, &not_used))
       break;
-    if (end_active_trans(thd))
+    if (trans_commit_implicit(thd))
       break;
     my_ok(thd);
     break;
@@ -1483,7 +1350,7 @@ bool dispatch_command(enum enum_server_c
 
   /* If commit fails, we should be able to reset the OK status. */
   thd->main_da.can_overwrite_status= TRUE;
-  ha_autocommit_or_rollback(thd, thd->is_error());
+  thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
   thd->main_da.can_overwrite_status= FALSE;
 
   thd->transaction.stmt.reset();
@@ -3349,7 +3216,7 @@ end_with_restore_list:
     thd->locked_tables_list.unlock_locked_tables(thd);
     if (thd->options & OPTION_TABLE_LOCK)
     {
-      end_active_trans(thd);
+      trans_commit_implicit(thd);
       thd->options&= ~(OPTION_TABLE_LOCK);
     }
     if (thd->global_read_lock)
@@ -3403,7 +3270,7 @@ end_with_restore_list:
       goto error;
     thd->locked_tables_list.unlock_locked_tables(thd);
     /* we must end the trasaction first, regardless of anything */
-    if (end_active_trans(thd))
+    if (trans_commit_implicit(thd))
       goto error;
 
     alloc_mdl_locks(all_tables, thd->locked_tables_list.locked_tables_root());
@@ -3426,8 +3293,8 @@ end_with_restore_list:
         can free its locks if LOCK TABLES locked some tables before finding
         that it can't lock a table in its list
       */
-      ha_autocommit_or_rollback(thd, 1);
-      end_active_trans(thd);
+      trans_rollback_stmt(thd);
+      trans_commit_implicit(thd);
       thd->options&= ~(OPTION_TABLE_LOCK);
     }
     else
@@ -3916,129 +3783,52 @@ end_with_restore_list:
     break;
 
   case SQLCOM_BEGIN:
-    if (thd->transaction.xid_state.xa_state != XA_NOTR)
-    {
-      my_error(ER_XAER_RMFAIL, MYF(0),
-               xa_state_names[thd->transaction.xid_state.xa_state]);
-      break;
-    }
     DEBUG_SYNC(thd, "before_begin_trans");
-    if (begin_trans(thd))
+    if (trans_begin(thd, lex->start_transaction_opt))
       goto error;
     my_ok(thd);
     break;
   case SQLCOM_COMMIT:
     DBUG_ASSERT(thd->lock == NULL ||
                 thd->locked_tables_mode == LTM_LOCK_TABLES);
-    if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE :
-                              lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
+    if (trans_commit(thd))
+      goto error;
+    /* Begin transaction with the same isolation level. */
+    if (lex->tx_chain && trans_begin(thd))
       goto error;
+    /* Disconnect the current client connection. */
+    if (lex->tx_release)
+      thd->killed= THD::KILL_CONNECTION;
     DEBUG_SYNC(thd, "after_commit");
     my_ok(thd);
     break;
   case SQLCOM_ROLLBACK:
     DBUG_ASSERT(thd->lock == NULL ||
                 thd->locked_tables_mode == LTM_LOCK_TABLES);
-    if (end_trans(thd, lex->tx_release ? ROLLBACK_RELEASE :
-                              lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK))
+    if (trans_rollback(thd))
+      goto error;
+    /* Begin transaction with the same isolation level. */
+    if (lex->tx_chain && trans_begin(thd))
       goto error;
+    /* Disconnect the current client connection. */
+    if (lex->tx_release)
+      thd->killed= THD::KILL_CONNECTION;
     my_ok(thd);
     break;
   case SQLCOM_RELEASE_SAVEPOINT:
-  {
-    SAVEPOINT *sv;
-    for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
-    {
-      if (my_strnncoll(system_charset_info,
-                       (uchar *)lex->ident.str, lex->ident.length,
-                       (uchar *)sv->name, sv->length) == 0)
-        break;
-    }
-    if (sv)
-    {
-      if (ha_release_savepoint(thd, sv))
-        res= TRUE; // cannot happen
-      else
-        my_ok(thd);
-      thd->transaction.savepoints=sv->prev;
-    }
-    else
-      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
+    if (trans_release_savepoint(thd, lex->ident))
+      goto error;
+    my_ok(thd);
     break;
-  }
   case SQLCOM_ROLLBACK_TO_SAVEPOINT:
-  {
-    SAVEPOINT *sv;
-    for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
-    {
-      if (my_strnncoll(system_charset_info,
-                       (uchar *)lex->ident.str, lex->ident.length,
-                       (uchar *)sv->name, sv->length) == 0)
-        break;
-    }
-    if (sv)
-    {
-      if (ha_rollback_to_savepoint(thd, sv))
-        res= TRUE; // cannot happen
-      else
-      {
-        if (((thd->options & OPTION_KEEP_LOG) || 
-             thd->transaction.all.modified_non_trans_table) &&
-            !thd->slave_thread)
-          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                       ER_WARNING_NOT_COMPLETE_ROLLBACK,
-                       ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
-        my_ok(thd);
-      }
-      thd->transaction.savepoints=sv;
-    }
-    else
-      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
+    if (trans_rollback_to_savepoint(thd, lex->ident))
+      goto error;
+    my_ok(thd);
     break;
-  }
   case SQLCOM_SAVEPOINT:
-    if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
-          thd->in_sub_stmt) || !opt_using_transactions)
-      my_ok(thd);
-    else
-    {
-      SAVEPOINT **sv, *newsv;
-      for (sv=&thd->transaction.savepoints; *sv; sv=&(*sv)->prev)
-      {
-        if (my_strnncoll(system_charset_info,
-                         (uchar *)lex->ident.str, lex->ident.length,
-                         (uchar *)(*sv)->name, (*sv)->length) == 0)
-          break;
-      }
-      if (*sv) /* old savepoint of the same name exists */
-      {
-        newsv=*sv;
-        ha_release_savepoint(thd, *sv); // it cannot fail
-        *sv=(*sv)->prev;
-      }
-      else if ((newsv=(SAVEPOINT *) alloc_root(&thd->transaction.mem_root,
-                                               savepoint_alloc_size)) == 0)
-      {
-        my_error(ER_OUT_OF_RESOURCES, MYF(0));
-        break;
-      }
-      newsv->name=strmake_root(&thd->transaction.mem_root,
-                               lex->ident.str, lex->ident.length);
-      newsv->length=lex->ident.length;
-      /*
-        if we'll get an error here, don't add new savepoint to the list.
-        we'll lose a little bit of memory in transaction mem_root, but it'll
-        be free'd when transaction ends anyway
-      */
-      if (ha_savepoint(thd, newsv))
-        res= TRUE;
-      else
-      {
-        newsv->prev=thd->transaction.savepoints;
-        thd->transaction.savepoints=newsv;
-        my_ok(thd);
-      }
-    }
+    if (trans_savepoint(thd, lex->ident))
+      goto error;
+    my_ok(thd);
     break;
   case SQLCOM_CREATE_PROCEDURE:
   case SQLCOM_CREATE_SPFUNCTION:
@@ -4380,7 +4170,7 @@ create_sp_error:
                                  lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
           goto error;
 
-        if (end_active_trans(thd)) 
+        if (trans_commit_implicit(thd))
           goto error;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
 	if (sp_automatic_privileges && !opt_noacl &&
@@ -4506,173 +4296,29 @@ create_sp_error:
     break;
   }
   case SQLCOM_XA_START:
-    if (thd->transaction.xid_state.xa_state == XA_IDLE &&
-        thd->lex->xa_opt == XA_RESUME)
-    {
-      if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
-      {
-        my_error(ER_XAER_NOTA, MYF(0));
-        break;
-      }
-      thd->transaction.xid_state.xa_state=XA_ACTIVE;
-      my_ok(thd);
-      break;
-    }
-    if (thd->lex->xa_opt != XA_NONE)
-    { // JOIN is not supported yet. TODO
-      my_error(ER_XAER_INVAL, MYF(0));
-      break;
-    }
-    if (thd->transaction.xid_state.xa_state != XA_NOTR)
-    {
-      my_error(ER_XAER_RMFAIL, MYF(0),
-               xa_state_names[thd->transaction.xid_state.xa_state]);
-      break;
-    }
-    if (thd->locked_tables_mode || thd->active_transaction())
-    {
-      my_error(ER_XAER_OUTSIDE, MYF(0));
-      break;
-    }
-    if (xid_cache_search(thd->lex->xid))
-    {
-      my_error(ER_XAER_DUPID, MYF(0));
-      break;
-    }
-    DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
-    thd->transaction.xid_state.xa_state=XA_ACTIVE;
-    thd->transaction.xid_state.xid.set(thd->lex->xid);
-    xid_cache_insert(&thd->transaction.xid_state);
-    thd->transaction.all.modified_non_trans_table= FALSE;
-    thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN);
-    thd->server_status|= SERVER_STATUS_IN_TRANS;
+    if (trans_xa_start(thd))
+      goto error;
     my_ok(thd);
     break;
   case SQLCOM_XA_END:
-    /* fake it */
-    if (thd->lex->xa_opt != XA_NONE)
-    { // SUSPEND and FOR MIGRATE are not supported yet. TODO
-      my_error(ER_XAER_INVAL, MYF(0));
-      break;
-    }
-    if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
-    {
-      my_error(ER_XAER_RMFAIL, MYF(0),
-               xa_state_names[thd->transaction.xid_state.xa_state]);
-      break;
-    }
-    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
-    {
-      my_error(ER_XAER_NOTA, MYF(0));
-      break;
-    }
-    thd->transaction.xid_state.xa_state=XA_IDLE;
+    if (trans_xa_end(thd))
+      goto error;
     my_ok(thd);
     break;
   case SQLCOM_XA_PREPARE:
-    if (thd->transaction.xid_state.xa_state != XA_IDLE)
-    {
-      my_error(ER_XAER_RMFAIL, MYF(0),
-               xa_state_names[thd->transaction.xid_state.xa_state]);
-      break;
-    }
-    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
-    {
-      my_error(ER_XAER_NOTA, MYF(0));
-      break;
-    }
-    if (ha_prepare(thd))
-    {
-      my_error(ER_XA_RBROLLBACK, MYF(0));
-      xid_cache_delete(&thd->transaction.xid_state);
-      thd->transaction.xid_state.xa_state=XA_NOTR;
-      break;
-    }
-    thd->transaction.xid_state.xa_state=XA_PREPARED;
+    if (trans_xa_prepare(thd))
+      goto error;
     my_ok(thd);
     break;
   case SQLCOM_XA_COMMIT:
-    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
-    {
-      XID_STATE *xs=xid_cache_search(thd->lex->xid);
-      if (!xs || xs->in_thd)
-        my_error(ER_XAER_NOTA, MYF(0));
-      else
-      {
-        ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
-        xid_cache_delete(xs);
-        my_ok(thd);
-      }
-      break;
-    }
-    if (thd->transaction.xid_state.xa_state == XA_IDLE &&
-        thd->lex->xa_opt == XA_ONE_PHASE)
-    {
-      int r;
-      if ((r= ha_commit(thd)))
-        my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
-      else
-        my_ok(thd);
-    }
-    else if (thd->transaction.xid_state.xa_state == XA_PREPARED &&
-             thd->lex->xa_opt == XA_NONE)
-    {
-      if (wait_if_global_read_lock(thd, 0, 0))
-      {
-        ha_rollback(thd);
-        my_error(ER_XAER_RMERR, MYF(0));
-      }
-      else
-      {
-        if (ha_commit_one_phase(thd, 1))
-          my_error(ER_XAER_RMERR, MYF(0));
-        else
-          my_ok(thd);
-        start_waiting_global_read_lock(thd);
-      }
-    }
-    else
-    {
-      my_error(ER_XAER_RMFAIL, MYF(0),
-               xa_state_names[thd->transaction.xid_state.xa_state]);
-      break;
-    }
-    thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
-    thd->transaction.all.modified_non_trans_table= FALSE;
-    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
-    xid_cache_delete(&thd->transaction.xid_state);
-    thd->transaction.xid_state.xa_state=XA_NOTR;
+    if (trans_xa_commit(thd))
+      goto error;
+    my_ok(thd);
     break;
   case SQLCOM_XA_ROLLBACK:
-    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
-    {
-      XID_STATE *xs=xid_cache_search(thd->lex->xid);
-      if (!xs || xs->in_thd)
-        my_error(ER_XAER_NOTA, MYF(0));
-      else
-      {
-        ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
-        xid_cache_delete(xs);
-        my_ok(thd);
-      }
-      break;
-    }
-    if (thd->transaction.xid_state.xa_state != XA_IDLE &&
-        thd->transaction.xid_state.xa_state != XA_PREPARED)
-    {
-      my_error(ER_XAER_RMFAIL, MYF(0),
-               xa_state_names[thd->transaction.xid_state.xa_state]);
-      break;
-    }
-    if (ha_rollback(thd))
-      my_error(ER_XAER_RMERR, MYF(0));
-    else
-      my_ok(thd);
-    thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
-    thd->transaction.all.modified_non_trans_table= FALSE;
-    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
-    xid_cache_delete(&thd->transaction.xid_state);
-    thd->transaction.xid_state.xa_state=XA_NOTR;
+    if (trans_xa_rollback(thd))
+      goto error;
+    my_ok(thd);
     break;
   case SQLCOM_XA_RECOVER:
     res= mysql_xa_recover(thd);

=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc	2008-07-15 16:29:51 +0000
+++ b/sql/sql_partition.cc	2008-07-31 20:31:54 +0000
@@ -37,6 +37,7 @@
 #include <errno.h>
 #include <m_ctype.h>
 #include "my_md5.h"
+#include "transaction.h"
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 #include "ha_partition.h"
@@ -3966,8 +3967,8 @@ static int fast_end_partition(THD *thd, 
   if (!is_empty)
     query_cache_invalidate3(thd, table_list, 0);
 
-  error= ha_autocommit_or_rollback(thd, 0);
-  if (end_active_trans(thd))
+  error= trans_commit_stmt(thd);
+  if (trans_commit_implicit(thd))
     error= 1;
 
   if (error)

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2008-07-26 16:38:20 +0000
+++ b/sql/sql_table.cc	2008-07-31 20:31:54 +0000
@@ -22,6 +22,7 @@
 #include "sp_head.h"
 #include "sql_trigger.h"
 #include "sql_show.h"
+#include "transaction.h"
 
 #ifdef __WIN__
 #include <io.h>
@@ -4217,8 +4218,8 @@ static bool mysql_admin_table(THD* thd, 
       DBUG_PRINT("admin", ("calling prepare_func"));
       switch ((*prepare_func)(thd, table, check_opt)) {
       case  1:           // error, message written to net
-        ha_autocommit_or_rollback(thd, 1);
-        end_trans(thd, ROLLBACK);
+        trans_rollback_stmt(thd);
+        trans_rollback(thd);
         close_thread_tables(thd);
         DBUG_PRINT("admin", ("simple error, admin next table"));
         continue;
@@ -4276,8 +4277,8 @@ static bool mysql_admin_table(THD* thd, 
       length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
                           table_name);
       protocol->store(buff, length, system_charset_info);
-      ha_autocommit_or_rollback(thd, 0);
-      end_trans(thd, COMMIT);
+      trans_commit_stmt(thd);
+      trans_commit(thd);
       close_thread_tables(thd);
       lex->reset_query_tables_list(FALSE);
       table->table=0;				// For query cache
@@ -4326,7 +4327,7 @@ static bool mysql_admin_table(THD* thd, 
            HA_ADMIN_NEEDS_ALTER))
       {
         DBUG_PRINT("admin", ("recreating table"));
-        ha_autocommit_or_rollback(thd, 1);
+        trans_rollback_stmt(thd);
         close_thread_tables(thd);
         tmp_disable_binlog(thd); // binlogging is done by caller if wanted
         result_code= mysql_recreate_table(thd, table);
@@ -4439,7 +4440,7 @@ send_result_message:
         "try with alter", so here we close the table, do an ALTER TABLE,
         reopen the table and do ha_innobase::analyze() on it.
       */
-      ha_autocommit_or_rollback(thd, 0);
+      trans_commit_stmt(thd);
       close_thread_tables(thd);
       TABLE_LIST *save_next_local= table->next_local,
                  *save_next_global= table->next_global;
@@ -4455,7 +4456,7 @@ send_result_message:
       */
       if (thd->main_da.is_ok())
         thd->main_da.reset_diagnostics_area();
-      ha_autocommit_or_rollback(thd, 0);
+      trans_commit_stmt(thd);
       close_thread_tables(thd);
       if (!result_code) // recreation went ok
       {
@@ -4544,8 +4545,8 @@ send_result_message:
         query_cache_invalidate3(thd, table->table, 0);
       }
     }
-    ha_autocommit_or_rollback(thd, 0);
-    end_trans(thd, COMMIT);
+    trans_commit_stmt(thd);
+    trans_commit_implicit(thd);
     close_thread_tables(thd);
     table->table=0;				// For query cache
     if (protocol->write())
@@ -4556,8 +4557,8 @@ send_result_message:
   DBUG_RETURN(FALSE);
 
 err:
-  ha_autocommit_or_rollback(thd, 1);
-  end_trans(thd, ROLLBACK);
+  trans_rollback_stmt(thd);
+  trans_rollback(thd);
   close_thread_tables(thd);			// Shouldn't be needed
   if (table)
     table->table=0;
@@ -5049,15 +5050,15 @@ mysql_discard_or_import_tablespace(THD *
   query_cache_invalidate3(thd, table_list, 0);
 
   /* The ALTER TABLE is always in its own transaction */
-  error = ha_autocommit_or_rollback(thd, 0);
-  if (end_active_trans(thd))
+  error= trans_commit_stmt(thd);
+  if (trans_commit_implicit(thd))
     error=1;
   if (error)
     goto err;
   write_bin_log(thd, FALSE, thd->query, thd->query_length);
 
 err:
-  ha_autocommit_or_rollback(thd, error);
+  trans_rollback_stmt(thd);
   thd->tablespace_op=FALSE;
 
   if (error == 0)
@@ -5814,8 +5815,8 @@ mysql_fast_or_online_alter_table(THD *th
     wait_if_global_read_lock(), which could create a deadlock if called
     with LOCK_open.
   */
-  error= ha_autocommit_or_rollback(thd, 0);
-  if (ha_commit(thd))
+  error= trans_commit_stmt(thd);
+  if (trans_commit_implicit(thd))
     error= 1;
 
   if (error)
@@ -6948,8 +6949,8 @@ view_err:
   }
   else
   {
-    error= ha_autocommit_or_rollback(thd, 0);
-    if (end_active_trans(thd))
+    error= trans_commit_stmt(thd);
+    if (trans_commit_implicit(thd))
       error= 1;
   }
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
@@ -7394,9 +7395,9 @@ err:
     Ensure that the new table is saved properly to disk so that we
     can do a rename
   */
-  if (ha_autocommit_or_rollback(thd, 0))
+  if (trans_commit_stmt(thd))
     error=1;
-  if (end_active_trans(thd))
+  if (trans_commit_implicit(thd))
     error=1;
 
   thd->variables.sql_mode= save_sql_mode;

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2008-07-25 17:21:55 +0000
+++ b/sql/sql_yacc.yy	2008-07-31 20:31:54 +0000
@@ -44,6 +44,7 @@
 #include "sp_rcontext.h"
 #include "sp.h"
 #include "event_parse_data.h"
+#include "transaction.h"
 #include <myisam.h>
 #include <myisammrg.h>
 

=== added file 'sql/transaction.cc'
--- a/sql/transaction.cc	1970-01-01 00:00:00 +0000
+++ b/sql/transaction.cc	2008-07-31 20:31:54 +0000
@@ -0,0 +1,581 @@
+/* Copyright (C) 2008 Sun/MySQL
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   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
+   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 */
+
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation				// gcc: Class implementation
+#endif
+
+#include "mysql_priv.h"
+#include "transaction.h"
+
+#ifdef WITH_MARIA_STORAGE_ENGINE
+#include "../storage/maria/ha_maria.h"
+#endif
+
+/* Conditions under which the transaction state must not change. */
+static bool trans_check(THD *thd)
+{
+  enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+  DBUG_ENTER("trans_check");
+
+  if (unlikely(thd->in_sub_stmt))
+    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+  if (xa_state != XA_NOTR)
+    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+  else
+    DBUG_RETURN(FALSE);
+
+  DBUG_RETURN(TRUE);
+}
+
+
+/**
+  Begin a new transaction.
+
+  @note Beginning a transaction implicitly commits any current
+        transaction and releases existing locks.
+
+  @param thd     Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_begin(THD *thd, uint flags)
+{
+  int res= FALSE;
+  DBUG_ENTER("trans_begin");
+
+  if (trans_check(thd))
+    DBUG_RETURN(TRUE);
+
+  thd->locked_tables_list.unlock_locked_tables(thd);
+
+  if (trans_commit_implicit(thd))
+    DBUG_RETURN(TRUE);
+
+  thd->options|= OPTION_BEGIN;
+  thd->server_status|= SERVER_STATUS_IN_TRANS;
+
+  if (flags & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
+    res= ha_start_consistent_snapshot(thd);
+
+  DBUG_RETURN(test(res));
+}
+
+
+/**
+  Commit the current transaction, making its changes permanent.
+
+  @param thd     Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_commit(THD *thd)
+{
+  int res;
+  DBUG_ENTER("trans_commit");
+
+  if (trans_check(thd))
+    DBUG_RETURN(TRUE);
+
+  thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+  res= ha_commit_trans(thd, TRUE);
+  thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+  thd->transaction.all.modified_non_trans_table= FALSE;
+
+  DBUG_RETURN(test(res));
+}
+
+
+/**
+  Implicitly commit the current transaction.
+
+  @note A implicit commit does not releases existing table locks.
+
+  @param thd     Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_commit_implicit(THD *thd)
+{
+  bool res= FALSE;
+  DBUG_ENTER("trans_commit_implicit");
+
+  if (trans_check(thd))
+    DBUG_RETURN(TRUE);
+
+  if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
+                      OPTION_TABLE_LOCK))
+  {
+    /* Safety if one did "drop table" on locked tables */
+    if (!thd->locked_tables_mode)
+      thd->options&= ~OPTION_TABLE_LOCK;
+    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+    res= test(ha_commit_trans(thd, TRUE));
+#ifdef WITH_MARIA_STORAGE_ENGINE
+    ha_maria::implicit_commit(thd, TRUE);
+#endif
+  }
+
+  thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+  thd->transaction.all.modified_non_trans_table= FALSE;
+
+  DBUG_RETURN(res);
+}
+
+
+/**
+  Rollback the current transaction, canceling its changes.
+
+  @param thd     Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_rollback(THD *thd)
+{
+  int res;
+  DBUG_ENTER("trans_rollback");
+
+  if (trans_check(thd))
+    DBUG_RETURN(TRUE);
+
+  thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+  res= ha_rollback_trans(thd, TRUE);
+  thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+  thd->transaction.all.modified_non_trans_table= FALSE;
+
+  DBUG_RETURN(test(res));
+}
+
+
+/**
+  Commit the single statement transaction.
+
+  @note Note that if the autocommit is on, then the following call
+        inside InnoDB will commit or rollback the whole transaction
+        (= the statement). The autocommit mechanism built into InnoDB
+        is based on counting locks, but if the user has used LOCK
+        TABLES then that mechanism does not know to do the commit.
+
+  @param thd     Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_commit_stmt(THD *thd)
+{
+  DBUG_ENTER("trans_commit_stmt");
+  int res= FALSE;
+  if (thd->transaction.stmt.ha_list)
+    res= ha_commit_trans(thd, FALSE);
+  DBUG_RETURN(test(res));
+}
+
+
+/**
+  Rollback the single statement transaction.
+
+  @param thd     Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+bool trans_rollback_stmt(THD *thd)
+{
+  DBUG_ENTER("trans_rollback_stmt");
+
+  if (thd->transaction.stmt.ha_list)
+  {
+    thd->transaction_rollback_request= FALSE;
+    ha_rollback_trans(thd, FALSE);
+    if (thd->transaction_rollback_request && !thd->in_sub_stmt)
+      ha_rollback_trans(thd, TRUE);
+  }
+
+  DBUG_RETURN(FALSE);
+}
+
+/* Find a named savepoint in the current transaction. */
+static SAVEPOINT **
+find_savepoint(THD *thd, LEX_STRING name)
+{
+  SAVEPOINT **sv= &thd->transaction.savepoints;
+
+  while (*sv)
+  {
+    if (my_strnncoll(system_charset_info, (uchar *) name.str, name.length,
+                     (uchar *) (*sv)->name, (*sv)->length) == 0)
+      break;
+    sv= &(*sv)->prev;
+  }
+
+  return sv;
+}
+
+
+/**
+  Set a named transaction savepoint.
+
+  @param thd    Current thread
+  @param name   Savepoint name
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_savepoint(THD *thd, LEX_STRING name)
+{
+  SAVEPOINT **sv, *newsv;
+  DBUG_ENTER("trans_savepoint");
+
+  if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
+        thd->in_sub_stmt) || !opt_using_transactions)
+    DBUG_RETURN(FALSE);
+
+  sv= find_savepoint(thd, name);
+
+  if (*sv) /* old savepoint of the same name exists */
+  {
+    newsv= *sv;
+    ha_release_savepoint(thd, *sv);
+    *sv= (*sv)->prev;
+  }
+  else if ((newsv= (SAVEPOINT *) alloc_root(&thd->transaction.mem_root,
+                                            savepoint_alloc_size)) == NULL)
+  {
+    my_error(ER_OUT_OF_RESOURCES, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  newsv->name= strmake_root(&thd->transaction.mem_root, name.str, name.length);
+  newsv->length= name.length;
+
+  /*
+    if we'll get an error here, don't add new savepoint to the list.
+    we'll lose a little bit of memory in transaction mem_root, but it'll
+    be free'd when transaction ends anyway
+  */
+  if (ha_savepoint(thd, newsv))
+    DBUG_RETURN(TRUE);
+
+  newsv->prev= thd->transaction.savepoints;
+  thd->transaction.savepoints= newsv;
+
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  Rollback a transaction to the named savepoint.
+
+  @note Modifications that the current transaction made to
+        rows after the savepoint was set are undone in the
+        rollback.
+
+  @note Savepoints that were set at a later time than the
+        named savepoint are deleted.
+
+  @param thd    Current thread
+  @param name   Savepoint name
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name)
+{
+  int res= FALSE;
+  SAVEPOINT *sv= *find_savepoint(thd, name);
+  DBUG_ENTER("trans_rollback_to_savepoint");
+
+  if (sv == NULL)
+  {
+    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", name.str);
+    DBUG_RETURN(TRUE);
+  }
+
+  if (ha_rollback_to_savepoint(thd, sv))
+    res= TRUE;
+  else if (((thd->options & OPTION_KEEP_LOG) ||
+            thd->transaction.all.modified_non_trans_table) &&
+           !thd->slave_thread)
+    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
+                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
+
+  thd->transaction.savepoints= sv;
+
+  DBUG_RETURN(test(res));
+}
+
+
+/**
+  Remove the named savepoint from the set of savepoints of
+  the current transaction.
+
+  @note No commit or rollback occurs. It is an error if the
+        savepoint does not exist.
+
+  @param thd    Current thread
+  @param name   Savepoint name
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_release_savepoint(THD *thd, LEX_STRING name)
+{
+  int res= FALSE;
+  SAVEPOINT *sv= *find_savepoint(thd, name);
+  DBUG_ENTER("trans_release_savepoint");
+
+  if (sv == NULL)
+  {
+    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", name.str);
+    DBUG_RETURN(TRUE);
+  }
+
+  if (ha_release_savepoint(thd, sv))
+    res= TRUE;
+
+  thd->transaction.savepoints=sv->prev;
+
+  DBUG_RETURN(test(res));
+}
+
+
+/**
+  Starts an XA transaction with the given xid value.
+
+  @param thd    Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_xa_start(THD *thd)
+{
+  enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+  DBUG_ENTER("trans_xa_start");
+
+  if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
+  {
+    bool not_equal= !thd->transaction.xid_state.xid.eq(thd->lex->xid);
+    if (not_equal)
+      my_error(ER_XAER_NOTA, MYF(0));
+    else
+      thd->transaction.xid_state.xa_state= XA_ACTIVE;
+    DBUG_RETURN(not_equal);
+  }
+
+  /* TODO: JOIN is not supported yet. */
+  if (thd->lex->xa_opt != XA_NONE)
+    my_error(ER_XAER_INVAL, MYF(0));
+  else if (xa_state != XA_NOTR)
+    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+  else if (thd->locked_tables_mode || thd->active_transaction())
+    my_error(ER_XAER_OUTSIDE, MYF(0));
+  else if (xid_cache_search(thd->lex->xid))
+    my_error(ER_XAER_DUPID, MYF(0));
+  else if (!trans_begin(thd))
+  {
+    DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
+    thd->transaction.xid_state.xa_state= XA_ACTIVE;
+    thd->transaction.xid_state.xid.set(thd->lex->xid);
+    xid_cache_insert(&thd->transaction.xid_state);
+    DBUG_RETURN(FALSE);
+  }
+
+  DBUG_RETURN(TRUE);
+}
+
+
+/**
+  Put a XA transaction in the IDLE state.
+
+  @param thd    Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_xa_end(THD *thd)
+{
+  DBUG_ENTER("trans_xa_end");
+
+  /* TODO: SUSPEND and FOR MIGRATE are not supported yet. */
+  if (thd->lex->xa_opt != XA_NONE)
+    my_error(ER_XAER_INVAL, MYF(0));
+  else if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
+    my_error(ER_XAER_RMFAIL, MYF(0),
+             xa_state_names[thd->transaction.xid_state.xa_state]);
+  else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+    my_error(ER_XAER_NOTA, MYF(0));
+  else
+    thd->transaction.xid_state.xa_state= XA_IDLE;
+
+  DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_IDLE);
+}
+
+
+/**
+  Put a XA transaction in the PREPARED state.
+
+  @param thd    Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_xa_prepare(THD *thd)
+{
+  DBUG_ENTER("trans_xa_prepare");
+
+  if (thd->transaction.xid_state.xa_state != XA_IDLE)
+    my_error(ER_XAER_RMFAIL, MYF(0),
+             xa_state_names[thd->transaction.xid_state.xa_state]);
+  else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+    my_error(ER_XAER_NOTA, MYF(0));
+  else if (ha_prepare(thd))
+  {
+    xid_cache_delete(&thd->transaction.xid_state);
+    thd->transaction.xid_state.xa_state= XA_NOTR;
+    my_error(ER_XA_RBROLLBACK, MYF(0));
+  }
+  else
+    thd->transaction.xid_state.xa_state= XA_PREPARED;
+
+  DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_PREPARED);
+}
+
+
+/**
+  Commit and terminate the a XA transaction.
+
+  @param thd    Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_xa_commit(THD *thd)
+{
+  bool res= TRUE;
+  enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+  DBUG_ENTER("trans_xa_commit");
+
+  if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+  {
+    XID_STATE *xs= xid_cache_search(thd->lex->xid);
+    bool not_found= !xs || xs->in_thd;
+    if (not_found)
+      my_error(ER_XAER_NOTA, MYF(0));
+    else
+    {
+      ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
+      xid_cache_delete(xs);
+    }
+    DBUG_RETURN(not_found);
+  }
+
+  if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
+  {
+    int r= ha_commit_trans(thd, TRUE);
+    if ((res= test(r)))
+      my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
+  }
+  else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
+  {
+    if (wait_if_global_read_lock(thd, 0, 0))
+    {
+      ha_rollback_trans(thd, TRUE);
+      my_error(ER_XAER_RMERR, MYF(0));
+    }
+    else
+    {
+      res= test(ha_commit_one_phase(thd, 1));
+      if (res)
+        my_error(ER_XAER_RMERR, MYF(0));
+      start_waiting_global_read_lock(thd);
+    }
+  }
+  else
+    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+
+  thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+  thd->transaction.all.modified_non_trans_table= FALSE;
+  thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+  xid_cache_delete(&thd->transaction.xid_state);
+  thd->transaction.xid_state.xa_state= XA_NOTR;
+
+  DBUG_RETURN(res);
+}
+
+
+/**
+  Roll back and terminate a XA transaction.
+
+  @param thd    Current thread
+
+  @retval FALSE  Success
+  @retval TRUE   Failure
+*/
+
+bool trans_xa_rollback(THD *thd)
+{
+  bool res= TRUE;
+  enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+  DBUG_ENTER("trans_xa_rollback");
+
+  if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+  {
+    XID_STATE *xs= xid_cache_search(thd->lex->xid);
+    bool not_found= !xs || xs->in_thd;
+    if (not_found)
+      my_error(ER_XAER_NOTA, MYF(0));
+    else
+    {
+      ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
+      xid_cache_delete(xs);
+    }
+    DBUG_RETURN(not_found);
+  }
+
+  if (xa_state != XA_IDLE && xa_state != XA_PREPARED)
+  {
+    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+    DBUG_RETURN(TRUE);
+  }
+
+  if ((res= test(ha_rollback_trans(thd, TRUE))))
+    my_error(ER_XAER_RMERR, MYF(0));
+
+  thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+  thd->transaction.all.modified_non_trans_table= FALSE;
+  thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+  xid_cache_delete(&thd->transaction.xid_state);
+  thd->transaction.xid_state.xa_state= XA_NOTR;
+
+  DBUG_RETURN(res);
+}

=== added file 'sql/transaction.h'
--- a/sql/transaction.h	1970-01-01 00:00:00 +0000
+++ b/sql/transaction.h	2008-07-31 20:31:54 +0000
@@ -0,0 +1,46 @@
+/* Copyright (C) 2008 Sun/MySQL
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   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
+   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 */
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface			/* gcc class implementation */
+#endif
+
+#ifndef TRANSACTION_H
+#define TRANSACTION_H
+
+class THD;
+
+/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
+#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT    (1U << 0)
+
+bool trans_begin(THD *thd, uint flags= 0);
+bool trans_commit(THD *thd);
+bool trans_commit_implicit(THD *thd);
+bool trans_rollback(THD *thd);
+
+bool trans_commit_stmt(THD *thd);
+bool trans_rollback_stmt(THD *thd);
+
+bool trans_savepoint(THD *thd, LEX_STRING name);
+bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name);
+bool trans_release_savepoint(THD *thd, LEX_STRING name);
+
+bool trans_xa_start(THD *thd);
+bool trans_xa_end(THD *thd);
+bool trans_xa_prepare(THD *thd);
+bool trans_xa_commit(THD *thd);
+bool trans_xa_rollback(THD *thd);
+
+#endif /* TRANSACTION_H */

=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc	2008-07-10 14:58:31 +0000
+++ b/storage/maria/ha_maria.cc	2008-07-31 20:31:54 +0000
@@ -2293,8 +2293,8 @@ int ha_maria::start_stmt(THD *thd, thr_l
 
   This can be considered a hack. When Maria loses HA_NO_TRANSACTIONS it will
   be participant in the connection's transaction and so the implicit commits
-  (ha_commit()) (like in end_active_trans()) will do the implicit commit
-  without need to call this function which can then be removed.
+  (ha_commit_trans()) (like in trans_commit_implicit()) will do the implicit
+  commit without need to call this function which can then be removed.
 
   @param  thd              THD object
   @param  new_trn          if a new transaction should be created; a new

Thread
bzr commit into mysql-6.0-runtime branch (davi:2690) WL#4284Davi Arnaut31 Jul
  • Re: bzr commit into mysql-6.0-runtime branch (davi:2690) WL#4284Konstantin Osipov6 Aug