Commit d42f973b authored by serg@sergbook.mysql.com's avatar serg@sergbook.mysql.com

merged

parents 0f9b9829 f5ff607c
......@@ -5,12 +5,9 @@ extra/yassl/src/Makefile)
AC_DEFUN([MYSQL_CHECK_YASSL], [
AC_MSG_CHECKING(for yaSSL)
AC_ARG_WITH([yassl],
[ --with-yassl Include the yaSSL support],
[yassl=yes],
[yassl=no])
AC_ARG_WITH([yassl], [ --with-yassl Include the yaSSL support],,)
if test "$yassl" = "yes"
if test "$with_yassl" = "yes"
then
if test "$openssl" != "no"
then
......@@ -30,5 +27,5 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [
AC_SUBST(openssl_libs)
AC_SUBST(openssl_includes)
AC_SUBST(yassl_dir)
AM_CONDITIONAL([HAVE_YASSL], [ test "$yassl" = "yes" ])
AM_CONDITIONAL([HAVE_YASSL], [ test "with_yassl" = "yes" ])
])
......@@ -130,6 +130,7 @@ AC_PROG_MAKE_SET
# Hack for OS X/Darwin and Metrowerks CodeWarrior
AC_ARG_WITH(darwin-mwcc,
[ --with-darwin-mwcc Use Metrowerks CodeWarrior wrappers on OS X/Darwin],[
if [ "with_darwin_mwcc" = yes ] ; then
builddir=`pwd`
ccwrapper="$builddir/support-files/MacOSX/mwcc-wrapper"
arwrapper="$builddir/support-files/MacOSX/mwar-wrapper"
......@@ -141,7 +142,7 @@ AC_ARG_WITH(darwin-mwcc,
export CC CXX LD AR RANLIB
AC_SUBST(AR)
AC_SUBST(RANLIB)
with_darwin_mwcc=yes
fi
])
AM_CONDITIONAL(DARWIN_MWCC, test x$with_darwin_mwcc = xyes)
......
......@@ -22,6 +22,8 @@ a
xa start 'testa','testb';
insert t1 values (30);
xa end 'testa','testb';
xa start 'testa','testb';
ERROR XAE08: XAER_DUPID: The XID already exists
xa start 0x7465737462, 0x2030405060, 0xb;
insert t1 values (40);
xa end 'testb',' 0@P`',11;
......@@ -35,11 +37,11 @@ formatID gtrid_length bqual_length data
11 5 5 testb 0@P`
1 5 5 testatestb
xa commit 'testb',0x2030405060,11;
ERROR XAE04: XAER_NOTA: Unknown XID
xa rollback 'testa','testb';
xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
select * from t1;
a
20
40
drop table t1;
......@@ -31,6 +31,9 @@ xa end 'testa','testb';
connect (con1,localhost,,,);
connection con1;
--error 1438
xa start 'testa','testb';
# gtrid [ , bqual [ , formatID ] ]
xa start 0x7465737462, 0x2030405060, 0xb;
insert t1 values (40);
......@@ -47,6 +50,7 @@ xa prepare 'testa','testb';
xa recover;
--error 1397
xa commit 'testb',0x2030405060,11;
xa rollback 'testa','testb';
......
......@@ -7032,7 +7032,7 @@ innobase_xa_prepare(
return(0);
}
trx->xid=thd->transaction.xid;
trx->xid=thd->transaction.xid_state.xid;
/* Release a possible FIFO ticket and search latch. Since we will
reserve the kernel mutex, we have to release the search system latch
......
......@@ -547,8 +547,8 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
trans->ht[trans->nht++]=ht_arg;
DBUG_ASSERT(*ht == ht_arg);
trans->no_2pc|=(ht_arg->prepare==0);
if (thd->transaction.xid.is_null())
thd->transaction.xid.set(thd->query_id);
if (thd->transaction.xid_state.xid.is_null())
thd->transaction.xid_state.xid.set(thd->query_id);
DBUG_VOID_RETURN;
}
......@@ -595,7 +595,7 @@ int ha_commit_trans(THD *thd, bool all)
THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
bool is_real_trans= all || thd->transaction.all.nht == 0;
handlerton **ht= trans->ht;
my_xid xid= thd->transaction.xid.get_my_xid();
my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
DBUG_ENTER("ha_commit_trans");
if (thd->in_sub_stmt)
......@@ -695,7 +695,7 @@ int ha_commit_one_phase(THD *thd, bool all)
trans->nht=0;
trans->no_2pc=0;
if (is_real_trans)
thd->transaction.xid.null();
thd->transaction.xid_state.xid.null();
if (all)
{
#ifdef HAVE_QUERY_CACHE
......@@ -751,7 +751,7 @@ int ha_rollback_trans(THD *thd, bool all)
trans->nht=0;
trans->no_2pc=0;
if (is_real_trans)
thd->transaction.xid.null();
thd->transaction.xid_state.xid.null();
if (all)
{
thd->variables.tx_isolation=thd->session_tx_isolation;
......@@ -945,6 +945,7 @@ int ha_recover(HASH *commit_list)
char buf[XIDDATASIZE*4+6]; // see xid_to_str
sql_print_information("ignore xid %s", xid_to_str(buf, list+i));
#endif
xid_cache_insert(list+i, XA_PREPARED);
found_foreign_xids++;
continue;
}
......@@ -1008,10 +1009,8 @@ bool mysql_xa_recover(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
handlerton **ht= handlertons, **end_ht=ht+total_ha;
bool error=TRUE;
int len, got;
XID *list=0;
int i=0;
XID_STATE *xs;
DBUG_ENTER("mysql_xa_recover");
field_list.push_back(new Item_int("formatID",0,11));
......@@ -1021,48 +1020,30 @@ bool mysql_xa_recover(THD *thd)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
{
list=(XID *)my_malloc(len*sizeof(XID), MYF(0));
}
if (!list)
{
my_error(ER_OUTOFMEMORY, MYF(0), len);
DBUG_RETURN(1);
}
for ( ; ht < end_ht ; ht++)
pthread_mutex_lock(&LOCK_xid_cache);
while (xs=(XID_STATE*)hash_element(&xid_cache, i++))
{
if (!(*ht)->recover)
continue;
while ((got=(*(*ht)->recover)(list, len)) > 0 )
if (xs->xa_state==XA_PREPARED)
{
XID *xid, *end;
for (xid=list, end=list+got; xid < end; xid++)
protocol->prepare_for_resend();
protocol->store_longlong((longlong)xs->xid.formatID, FALSE);
protocol->store_longlong((longlong)xs->xid.gtrid_length, FALSE);
protocol->store_longlong((longlong)xs->xid.bqual_length, FALSE);
protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
&my_charset_bin);
if (protocol->write())
{
if (xid->get_my_xid())
continue; // skip "our" xids
protocol->prepare_for_resend();
protocol->store_longlong((longlong)xid->formatID, FALSE);
protocol->store_longlong((longlong)xid->gtrid_length, FALSE);
protocol->store_longlong((longlong)xid->bqual_length, FALSE);
protocol->store(xid->data, xid->gtrid_length+xid->bqual_length,
&my_charset_bin);
if (protocol->write())
goto err;
pthread_mutex_unlock(&LOCK_xid_cache);
DBUG_RETURN(1);
}
if (got < len)
break;
}
}
error=FALSE;
pthread_mutex_unlock(&LOCK_xid_cache);
send_eof(thd);
err:
my_free((gptr)list, MYF(0));
DBUG_RETURN(error);
DBUG_RETURN(0);
}
/*
......@@ -1660,7 +1641,7 @@ void handler::print_error(int error, myf errflag)
}
case HA_ERR_NULL_IN_SPATIAL:
textno= ER_UNKNOWN_ERROR;
DBUG_VOID_RETURN;
break;
case HA_ERR_FOUND_DUPP_UNIQUE:
textno=ER_DUP_UNIQUE;
break;
......@@ -1683,8 +1664,8 @@ void handler::print_error(int error, myf errflag)
textno=ER_CRASHED_ON_REPAIR;
break;
case HA_ERR_OUT_OF_MEM:
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), errflag);
DBUG_VOID_RETURN;
textno=ER_OUT_OF_RESOURCES;
break;
case HA_ERR_WRONG_COMMAND:
textno=ER_ILLEGAL_HA;
break;
......@@ -1695,10 +1676,8 @@ void handler::print_error(int error, myf errflag)
textno=ER_UNSUPPORTED_EXTENSION;
break;
case HA_ERR_RECORD_FILE_FULL:
textno=ER_RECORD_FILE_FULL;
break;
case HA_ERR_INDEX_FILE_FULL:
textno= errno;
textno=ER_RECORD_FILE_FULL;
break;
case HA_ERR_LOCK_WAIT_TIMEOUT:
textno=ER_LOCK_WAIT_TIMEOUT;
......
......@@ -227,11 +227,11 @@ struct xid_t {
char data[XIDDATASIZE]; // not \0-terminated !
bool eq(struct xid_t *xid)
{ return !memcmp(this, xid, sizeof(long)*3+gtrid_length+bqual_length); }
{ return !memcmp(this, xid, length()); }
bool eq(long g, long b, const char *d)
{ return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
void set(struct xid_t *xid)
{ memcpy(this, xid, sizeof(long)*3+xid->gtrid_length+xid->bqual_length); }
{ memcpy(this, xid, xid->length()); }
void set(long f, const char *g, long gl, const char *b, long bl)
{
formatID= f;
......@@ -270,6 +270,11 @@ struct xid_t {
!memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ?
quick_get_my_xid() : 0;
}
uint length()
{
return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+
gtrid_length+bqual_length;
}
};
typedef struct xid_t XID;
......
......@@ -393,6 +393,10 @@ struct sql_ex_info
#define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_AUTO_IS_NULL | \
OPTION_NO_FOREIGN_KEY_CHECKS | OPTION_RELAXED_UNIQUE_CHECKS)
#if OPTIONS_WRITTEN_TO_BIN_LOG != ((1L << 14) | (1L << 26) | (1L << 27))
#error OPTIONS_WRITTEN_TO_BIN_LOG must NOT change their values!
#endif
enum Log_event_type
{
/*
......
......@@ -1050,6 +1050,7 @@ void clean_up(bool print_message)
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
if (tc_log)
tc_log->close();
xid_cache_free();
delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
multi_keycache_free();
end_thr_alarm(1); /* Free allocated memory */
......@@ -2920,6 +2921,11 @@ server.");
using_update_log=1;
}
if (xid_cache_init())
{
sql_print_error("Out of memory");
unireg_abort(1);
}
if (ha_init())
{
sql_print_error("Can't init databases");
......
......@@ -5393,3 +5393,5 @@ ER_WARN_CANT_DROP_DEFAULT_KEYCACHE
ger "Der Default-Keycache kann nicht gelscht werden"
ER_TOO_BIG_DISPLAYWIDTH 42000 S1009
eng "Display width out of range for column '%-.64s' (max = %d)"
ER_XAER_DUPID XAE08
eng "XAER_DUPID: The XID already exists"
......@@ -501,7 +501,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
*/
bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt));
if (!thd->active_transaction())
thd->transaction.xid.null();
thd->transaction.xid_state.xid.null();
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */
if (!lock_in_use)
......
......@@ -323,7 +323,8 @@ void THD::init_for_queries()
variables.trans_alloc_block_size,
variables.trans_prealloc_size);
#endif
transaction.xid.null();
transaction.xid_state.xid.null();
transaction.xid_state.in_thd=1;
}
......@@ -358,9 +359,15 @@ void THD::cleanup(void)
{
DBUG_ENTER("THD::cleanup");
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
if (transaction.xa_state != XA_PREPARED)
if (transaction.xid_state.xa_state == XA_PREPARED)
{
#error xid_state in the cache should be replaced by the allocated value
}
#endif
{
ha_rollback(this);
xid_cache_delete(&transaction.xid_state);
}
if (locked_tables)
{
lock=locked_tables; locked_tables=0;
......@@ -1836,3 +1843,81 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
set_open_tables_state(backup);
DBUG_VOID_RETURN;
}
pthread_mutex_t LOCK_xid_cache;
HASH xid_cache;
static byte *xid_get_hash_key(const byte *ptr,uint *length,
my_bool not_used __attribute__((unused)))
{
*length=((XID_STATE*)ptr)->xid.length();
return (byte *)&((XID_STATE*)ptr)->xid;
}
static void xid_free_hash (void *ptr)
{
if (!((XID_STATE*)ptr)->in_thd)
my_free((byte *)ptr, MYF(0));
}
bool xid_cache_init()
{
pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
xid_get_hash_key, xid_free_hash, 0) != 0;
}
void xid_cache_free()
{
if (hash_inited(&xid_cache))
{
hash_free(&xid_cache);
pthread_mutex_destroy(&LOCK_xid_cache);
}
}
XID_STATE *xid_cache_search(XID *xid)
{
pthread_mutex_lock(&LOCK_xid_cache);
XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, (byte *)xid, xid->length());
pthread_mutex_unlock(&LOCK_xid_cache);
return res;
}
bool xid_cache_insert(XID *xid, enum xa_states xa_state)
{
XID_STATE *xs;
my_bool res;
pthread_mutex_lock(&LOCK_xid_cache);
if (hash_search(&xid_cache, (byte *)xid, xid->length()))
res=0;
else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
res=1;
else
{
xs->xa_state=xa_state;
xs->xid.set(xid);
xs->in_thd=0;
res=my_hash_insert(&xid_cache, (byte*)xs);
}
pthread_mutex_unlock(&LOCK_xid_cache);
return res;
}
bool xid_cache_insert(XID_STATE *xid_state)
{
pthread_mutex_lock(&LOCK_xid_cache);
DBUG_ASSERT(hash_search(&xid_cache, (byte *)&xid_state->xid,
xid_state->xid.length())==0);
my_bool res=my_hash_insert(&xid_cache, (byte*)xid_state);
pthread_mutex_unlock(&LOCK_xid_cache);
return res;
}
void xid_cache_delete(XID_STATE *xid_state)
{
pthread_mutex_lock(&LOCK_xid_cache);
hash_delete(&xid_cache, (byte *)xid_state);
pthread_mutex_unlock(&LOCK_xid_cache);
}
......@@ -351,8 +351,6 @@ class MYSQL_LOG: public TC_LOG
inline uint32 get_open_count() { return open_count; }
};
/* character conversion tables */
typedef struct st_copy_info {
ha_rows records;
......@@ -564,11 +562,11 @@ struct system_variables
my_bool ndb_use_transactions;
#endif /* HAVE_NDBCLUSTER_DB */
my_bool old_passwords;
/* Only charset part of these variables is sensible */
CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_results;
/* Both charset and collation parts of these variables are important */
CHARSET_INFO *collation_server;
CHARSET_INFO *collation_database;
......@@ -631,7 +629,7 @@ typedef struct system_status_var
ulong filesort_range_count;
ulong filesort_rows;
ulong filesort_scan_count;
/* Ppepared statements and binary protocol */
/* Prepared statements and binary protocol */
ulong com_stmt_prepare;
ulong com_stmt_execute;
ulong com_stmt_send_long_data;
......@@ -656,8 +654,8 @@ void free_tmp_table(THD *thd, TABLE *entry);
/* The following macro is to make init of Query_arena simpler */
#ifndef DBUG_OFF
#define INIT_ARENA_DBUG_INFO is_backup_arena= 0
#else
#define INIT_ARENA_DBUG_INFO
#else
#define INIT_ARENA_DBUG_INFO
#endif
......@@ -925,6 +923,22 @@ struct st_savepoint {
enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED};
extern const char *xa_state_names[];
typedef struct st_xid_state {
/* For now, this is only used to catch duplicated external xids */
XID xid; // transaction identifier
enum xa_states xa_state; // used by external XA only
bool in_thd;
} XID_STATE;
extern pthread_mutex_t LOCK_xid_cache;
extern HASH xid_cache;
bool xid_cache_init(void);
void xid_cache_free(void);
XID_STATE *xid_cache_search(XID *xid);
bool xid_cache_insert(XID *xid, enum xa_states xa_state);
bool xid_cache_insert(XID_STATE *xid_state);
void xid_cache_delete(XID_STATE *xid_state);
/*
A registry for item tree transformations performed during
query optimization. We register only those changes which require
......@@ -946,7 +960,7 @@ enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1,
/*
Class that holds information about tables which were open and locked
Class that holds information about tables which were opened and locked
by the thread. It is also used to save/restore this information in
push_open_tables_state()/pop_open_tables_state().
*/
......@@ -1068,7 +1082,7 @@ class THD :public Statement,
// the lock_id of a cursor.
pthread_mutex_t LOCK_delete; // Locked before thd is deleted
/* all prepared statements and cursors of this connection */
Statement_map stmt_map;
Statement_map stmt_map;
/*
A pointer to the stack frame of handle_one_connection(),
which is called first in the thread for handling a client
......@@ -1138,10 +1152,10 @@ class THD :public Statement,
thr_lock_type update_lock_default;
delayed_insert *di;
my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */
/* TRUE if we are inside of trigger or stored function. */
bool in_sub_stmt;
/* container for handler's private per-connection data */
void *ha_data[MAX_HA];
struct st_transactions {
......@@ -1149,8 +1163,7 @@ class THD :public Statement,
THD_TRANS all; // Trans since BEGIN WORK
THD_TRANS stmt; // Trans for current statement
bool on; // see ha_enable_transaction()
XID xid; // transaction identifier
enum xa_states xa_state; // used by external XA only
XID_STATE xid_state;
/*
Tables changed in transaction (that must be invalidated in query cache).
List contain only transactional tables, that not invalidated in query
......@@ -1170,7 +1183,7 @@ class THD :public Statement,
st_transactions()
{
bzero((char*)this, sizeof(*this));
xid.null();
xid_state.xid.null();
init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
}
#endif
......
......@@ -2017,7 +2017,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
*/
bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt));
if (!thd->active_transaction())
thd->transaction.xid.null();
thd->transaction.xid_state.xid.null();
/* report error issued during command execution */
if (thd->killed_errno() && !thd->net.report_error)
......@@ -4504,14 +4504,15 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_XA_START:
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
if (thd->transaction.xid_state.xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_RESUME)
{
if (! thd->transaction.xid.eq(thd->lex->xid))
if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
}
thd->transaction.xa_state=XA_ACTIVE;
thd->transaction.xid_state.xa_state=XA_ACTIVE;
send_ok(thd);
break;
}
......@@ -4520,10 +4521,10 @@ mysql_execute_command(THD *thd)
my_error(ER_XAER_INVAL, MYF(0));
break;
}
if (thd->transaction.xa_state != XA_NOTR)
if (thd->transaction.xid_state.xa_state != XA_NOTR)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (thd->active_transaction() || thd->locked_tables)
......@@ -4531,9 +4532,15 @@ mysql_execute_command(THD *thd)
my_error(ER_XAER_OUTSIDE, MYF(0));
break;
}
DBUG_ASSERT(thd->transaction.xid.is_null());
thd->transaction.xa_state=XA_ACTIVE;
thd->transaction.xid.set(thd->lex->xid);
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->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
......@@ -4546,28 +4553,28 @@ mysql_execute_command(THD *thd)
my_error(ER_XAER_INVAL, MYF(0));
break;
}
if (thd->transaction.xa_state != XA_ACTIVE)
if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
}
thd->transaction.xa_state=XA_IDLE;
thd->transaction.xid_state.xa_state=XA_IDLE;
send_ok(thd);
break;
case SQLCOM_XA_PREPARE:
if (thd->transaction.xa_state != XA_IDLE)
if (thd->transaction.xid_state.xa_state != XA_IDLE)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
......@@ -4575,22 +4582,28 @@ mysql_execute_command(THD *thd)
if (ha_prepare(thd))
{
my_error(ER_XA_RBROLLBACK, MYF(0));
thd->transaction.xa_state=XA_NOTR;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
break;
}
thd->transaction.xa_state=XA_PREPARED;
thd->transaction.xid_state.xa_state=XA_PREPARED;
send_ok(thd);
break;
case SQLCOM_XA_COMMIT:
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 1)))
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);
send_ok(thd);
}
break;
}
if (thd->transaction.xa_state == XA_IDLE &&
if (thd->transaction.xid_state.xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_ONE_PHASE)
{
int r;
......@@ -4599,7 +4612,7 @@ mysql_execute_command(THD *thd)
else
send_ok(thd);
}
else if (thd->transaction.xa_state == XA_PREPARED &&
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))
......@@ -4619,27 +4632,33 @@ mysql_execute_command(THD *thd)
else
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
thd->transaction.xa_state=XA_NOTR;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
break;
case SQLCOM_XA_ROLLBACK:
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 0)))
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);
send_ok(thd);
}
break;
}
if (thd->transaction.xa_state != XA_IDLE &&
thd->transaction.xa_state != XA_PREPARED)
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.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (ha_rollback(thd))
......@@ -4648,7 +4667,8 @@ mysql_execute_command(THD *thd)
send_ok(thd);
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
thd->transaction.xa_state=XA_NOTR;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
break;
case SQLCOM_XA_RECOVER:
res= mysql_xa_recover(thd);
......
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