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` ( ...@@ -1895,3 +1895,21 @@ t1 CREATE TABLE `t1` (
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 ) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
drop table t1; drop table t1;
set storage_engine=MyISAM; 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; ...@@ -973,3 +973,24 @@ drop table t1;
# End varchar test # End varchar test
eval set storage_engine=$default; 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); ...@@ -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 int check_pseudo_thread_id(THD *thd, set_var *var);
static bool set_log_bin(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 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 void fix_tx_isolation(THD *thd, enum_var_type type);
static int check_completion_type(THD *thd, set_var *var); static int check_completion_type(THD *thd, set_var *var);
static void fix_completion_type(THD *thd, enum_var_type type); 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", ...@@ -386,7 +387,8 @@ sys_var_long_ptr sys_thread_cache_size("thread_cache_size",
sys_var_thd_enum sys_tx_isolation("tx_isolation", sys_var_thd_enum sys_tx_isolation("tx_isolation",
&SV::tx_isolation, &SV::tx_isolation,
&tx_isolation_typelib, &tx_isolation_typelib,
fix_tx_isolation); fix_tx_isolation,
check_tx_isolation);
sys_var_thd_ulong sys_tmp_table_size("tmp_table_size", sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size); &SV::tmp_table_size);
sys_var_bool_ptr sys_timed_mutexes("timed_mutexes", 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) ...@@ -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 If one doesn't use the SESSION modifier, the isolation level
is only active for the next command is only active for the next command
*/ */
static void fix_tx_isolation(THD *thd, enum_var_type type) static void fix_tx_isolation(THD *thd, enum_var_type type)
{ {
if (type == OPT_SESSION) if (type == OPT_SESSION)
......
...@@ -325,19 +325,31 @@ class sys_var_thd_enum :public sys_var_thd ...@@ -325,19 +325,31 @@ class sys_var_thd_enum :public sys_var_thd
protected: protected:
ulong SV::*offset; ulong SV::*offset;
TYPELIB *enum_names; TYPELIB *enum_names;
sys_check_func check_func;
public: public:
sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg, sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg,
TYPELIB *typelib) 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, sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg,
TYPELIB *typelib, TYPELIB *typelib,
sys_after_update_func func) 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) 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); bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type); void set_default(THD *thd, enum_var_type type);
......
...@@ -5421,3 +5421,5 @@ ER_NO_REFERENCED_ROW_2 23000 ...@@ -5421,3 +5421,5 @@ ER_NO_REFERENCED_ROW_2 23000
eng "Cannot add or update a child row: a foreign key constraint fails (%.192s)" eng "Cannot add or update a child row: a foreign key constraint fails (%.192s)"
ER_SP_BAD_VAR_SHADOW 42000 ER_SP_BAD_VAR_SHADOW 42000
eng "Variable '%-.64s' must be quoted with `...`, or renamed" 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,8 +8002,7 @@ sys_option_value: ...@@ -8002,8 +8002,7 @@ sys_option_value:
| option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types | option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
{ {
LEX *lex=Lex; LEX *lex=Lex;
if ($1) lex->option_type= $1;
lex->option_type= $1;
lex->var_list.push_back(new set_var(lex->option_type, lex->var_list.push_back(new set_var(lex->option_type,
find_sys_var("tx_isolation"), find_sys_var("tx_isolation"),
&null_lex_str, &null_lex_str,
......
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