Commit d68354d5 authored by unknown's avatar unknown

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
......@@ -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;
......@@ -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
......@@ -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)
......
......@@ -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);
......
......@@ -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"
......@@ -8002,7 +8002,6 @@ sys_option_value:
| option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
{
LEX *lex=Lex;
if ($1)
lex->option_type= $1;
lex->var_list.push_back(new set_var(lex->option_type,
find_sys_var("tx_isolation"),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment