Skip to content

Commit 88db7d8

Browse files
committed
Implementation of enforce_autocommit_on_reads
See issue #485
1 parent 9353560 commit 88db7d8

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

include/MySQL_Session.h

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class Query_Info {
3434
void begin(unsigned char *_p, int len, bool mysql_header=false);
3535
void end();
3636
char *get_digest_text();
37+
bool is_select_NOT_for_update();
3738
};
3839

3940
class MySQL_Session

lib/MySQL_Session.cpp

+49-2
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,28 @@ char * Query_Info::get_digest_text() {
153153
return GloQPro->get_digest_text(&QueryParserArgs);
154154
}
155155

156+
bool Query_Info::is_select_NOT_for_update() {
157+
// to avoid an expensive strlen() on the digest_text, we consider only the real query
158+
if (QueryPointer==NULL) {
159+
return false;
160+
}
161+
if (QueryLength<7) {
162+
return false;
163+
}
164+
if (strncasecmp((char *)QueryPointer,(char *)"SELECT ",7)) {
165+
return false;
166+
}
167+
// if we arrive till here, it is a SELECT
168+
if (QueryLength>=17) {
169+
char *p=(char *)QueryPointer;
170+
p+=QueryLength-11;
171+
if (strncasecmp(p," FOR UPDATE",11)==0) {
172+
return false;
173+
}
174+
}
175+
return true;
176+
}
177+
156178
void * MySQL_Session::operator new(size_t size) {
157179
return l_alloc(size);
158180
}
@@ -388,6 +410,7 @@ bool MySQL_Session::handler_SetAutocommit(PtrSize_t *pkt) {
388410

389411
if (fd==0) {
390412
autocommit=false; // we set it, no matter if already set or not
413+
/*
391414
if (nTrx) {
392415
// there is an active transaction, we need to forward it
393416
// because this can potentially close the transaction
@@ -398,6 +421,11 @@ bool MySQL_Session::handler_SetAutocommit(PtrSize_t *pkt) {
398421
// just return OK
399422
goto __ret_autocommit_OK;
400423
}
424+
*/
425+
// it turned out I was wrong
426+
// set autocommit=0 has no effect if there is an acrive transaction
427+
// therefore, we never forward set autocommit = 0
428+
goto __ret_autocommit_OK;
401429
}
402430
__ret_autocommit_OK:
403431
client_myds->DSS=STATE_QUERY_SENT_NET;
@@ -416,6 +444,14 @@ bool MySQL_Session::handler_SetAutocommit(PtrSize_t *pkt) {
416444
}
417445

418446
bool MySQL_Session::handler_special_queries(PtrSize_t *pkt) {
447+
448+
if (handler_SetAutocommit(pkt) == true) {
449+
return true;
450+
}
451+
if (handler_CommitRollback(pkt) == true) {
452+
return true;
453+
}
454+
419455
if (pkt->size==SELECT_LAST_INSERT_ID_LEN+5 && strncasecmp((char *)SELECT_LAST_INSERT_ID,(char *)pkt->ptr+5,pkt->size-5)==0) {
420456
char buf[16];
421457
sprintf(buf,"%u",last_insert_id);
@@ -830,8 +866,19 @@ int MySQL_Session::handler() {
830866
NEXT_IMMEDIATE(CHANGING_CHARSET);
831867
}
832868
if (autocommit != mybe->server_myds->myconn->IsAutoCommit()) {
833-
previous_status.push(PROCESSING_QUERY);
834-
NEXT_IMMEDIATE(CHANGING_AUTOCOMMIT);
869+
// see case #485
870+
if (mysql_thread___enforce_autocommit_on_reads == false) {
871+
// enforce_autocommit_on_reads is disabled
872+
// we need to check if it is a SELECT not FOR UPDATE
873+
if (CurrentQuery.is_select_NOT_for_update()==false) {
874+
previous_status.push(PROCESSING_QUERY);
875+
NEXT_IMMEDIATE(CHANGING_AUTOCOMMIT);
876+
}
877+
} else {
878+
// in every other cases, enforce autocommit
879+
previous_status.push(PROCESSING_QUERY);
880+
NEXT_IMMEDIATE(CHANGING_AUTOCOMMIT);
881+
}
835882
}
836883
}
837884
status=PROCESSING_QUERY;

0 commit comments

Comments
 (0)