Commit d68354d5 authored by unknown's avatar unknown
Browse files

Fix handling of "SET TRANSACTION ISOLATION LEVEL ...". (Bug #7955)


mysql-test/r/bdb.result:
  Add results
mysql-test/t/bdb.test:
  Add new test
sql/set_var.cc:
  Refuse attempts to change tx_isolation while a transaction is in progress.
sql/set_var.h:
  Support check function for sys_var_thd_enum
sql/share/errmsg.txt:
  Add new error message
sql/sql_yacc.yy:
  Make sure that lex->option_type always gets set in 'SET TRANSACTION ...'
parent 2b35ab12
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -1895,3 +1895,21 @@ t1 CREATE TABLE `t1` (
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
drop table t1;
set storage_engine=MyISAM;
create table t1 (a int) engine=bdb;
set session transaction isolation level repeatable read;
set transaction isolation level serializable;
begin;
select @@tx_isolation;
@@tx_isolation
SERIALIZABLE
insert into t1 values (1);
set transaction isolation level read committed;
ERROR 25001: Transaction isolation level can't be changed while a transaction is in progress
rollback;
begin;
select @@tx_isolation;
@@tx_isolation
REPEATABLE-READ
insert into t1 values (1);
rollback;
drop table t1;
+21 −0
Original line number Diff line number Diff line
@@ -973,3 +973,24 @@ drop table t1;

# End varchar test
eval set storage_engine=$default;

#
# Bug #7955: SET TRANSACTION ISIOLATION LEVEL lives longer than next
# transaciton
#
create table t1 (a int) engine=bdb;
set session transaction isolation level repeatable read;
set transaction isolation level serializable;
begin;
select @@tx_isolation;
insert into t1 values (1);
--error ER_CANT_CHANGE_TX_ISOLATION
set transaction isolation level read committed;
rollback;
begin;
select @@tx_isolation;
insert into t1 values (1);
rollback;
drop table t1;

# End of 5.0 tests
+17 −2
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ static bool set_log_update(THD *thd, set_var *var);
static int  check_pseudo_thread_id(THD *thd, set_var *var);
static bool set_log_bin(THD *thd, set_var *var);
static void fix_low_priority_updates(THD *thd, enum_var_type type);
static int check_tx_isolation(THD *thd, set_var *var);
static void fix_tx_isolation(THD *thd, enum_var_type type);
static int check_completion_type(THD *thd, set_var *var);
static void fix_completion_type(THD *thd, enum_var_type type);
@@ -386,7 +387,8 @@ sys_var_long_ptr sys_thread_cache_size("thread_cache_size",
sys_var_thd_enum	sys_tx_isolation("tx_isolation",
					 &SV::tx_isolation,
					 &tx_isolation_typelib,
					 fix_tx_isolation);
					 fix_tx_isolation,
					 check_tx_isolation);
sys_var_thd_ulong	sys_tmp_table_size("tmp_table_size",
					   &SV::tmp_table_size);
sys_var_bool_ptr  sys_timed_mutexes("timed_mutexes",
@@ -1163,11 +1165,24 @@ static void fix_max_join_size(THD *thd, enum_var_type type)
}


/*
  Can't change the 'next' tx_isolation while we are already in
  a transaction
*/
static int check_tx_isolation(THD *thd, set_var *var)
{
  if (var->type == OPT_DEFAULT && (thd->server_status & SERVER_STATUS_IN_TRANS))
  {
    my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0));
    return 1;
  }
  return 0;
}

/*
  If one doesn't use the SESSION modifier, the isolation level
  is only active for the next command
*/

static void fix_tx_isolation(THD *thd, enum_var_type type)
{
  if (type == OPT_SESSION)
+15 −3
Original line number Diff line number Diff line
@@ -325,19 +325,31 @@ class sys_var_thd_enum :public sys_var_thd
protected:
  ulong SV::*offset;
  TYPELIB *enum_names;
  sys_check_func check_func;
public:
  sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg,
		   TYPELIB *typelib)
    :sys_var_thd(name_arg), offset(offset_arg), enum_names(typelib)
    :sys_var_thd(name_arg), offset(offset_arg), enum_names(typelib),
    check_func(0)
  {}
  sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg,
		   TYPELIB *typelib,
		   sys_after_update_func func)
    :sys_var_thd(name_arg,func), offset(offset_arg), enum_names(typelib)
    :sys_var_thd(name_arg,func), offset(offset_arg), enum_names(typelib),
    check_func(0)
  {}
  sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg,
		   TYPELIB *typelib, sys_after_update_func func,
                   sys_check_func check)
    :sys_var_thd(name_arg,func), offset(offset_arg), enum_names(typelib),
    check_func(check)
  {}
  bool check(THD *thd, set_var *var)
  {
    return check_enum(thd, var, enum_names);
    int ret= 0;
    if (check_func)
      ret= (*check_func)(thd, var);
    return ret ? ret : check_enum(thd, var, enum_names);
  }
  bool update(THD *thd, set_var *var);
  void set_default(THD *thd, enum_var_type type);
+2 −0
Original line number Diff line number Diff line
@@ -5421,3 +5421,5 @@ ER_NO_REFERENCED_ROW_2 23000
	eng "Cannot add or update a child row: a foreign key constraint fails (%.192s)"
ER_SP_BAD_VAR_SHADOW 42000
	eng "Variable '%-.64s' must be quoted with `...`, or renamed"
ER_CANT_CHANGE_TX_ISOLATION 25001
	eng "Transaction isolation level can't be changed while a transaction is in progress"
Loading