Changed variable type which includes information of query type returned by query classifier.

As a consequence, if autocommit is enabled, active transaction(s) are implicitly committed and MaxScale detects that implicit commit.
This commit is contained in:
VilhoRaatikka
2014-03-20 12:15:57 +02:00
parent fcf7d37114
commit 288ca68677
3 changed files with 88 additions and 76 deletions

View File

@ -343,9 +343,9 @@ return_here:
* restrictive, for example, QUERY_TYPE_READ is smaller than QUERY_TYPE_WRITE. * restrictive, for example, QUERY_TYPE_READ is smaller than QUERY_TYPE_WRITE.
* *
*/ */
static skygw_query_type_t set_query_type( static u_int8_t set_query_type(
skygw_query_type_t* qtype, u_int8_t* qtype,
skygw_query_type_t new_type) u_int8_t new_type)
{ {
*qtype = MAX(*qtype, new_type); *qtype = MAX(*qtype, new_type);
return *qtype; return *qtype;
@ -371,6 +371,7 @@ static skygw_query_type_t resolve_query_type(
THD* thd) THD* thd)
{ {
skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN; skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN;
u_int8_t type = QUERY_TYPE_UNKNOWN;
LEX* lex; LEX* lex;
Item* item; Item* item;
/** /**
@ -389,7 +390,7 @@ static skygw_query_type_t resolve_query_type(
/** SELECT ..INTO variable|OUTFILE|DUMPFILE */ /** SELECT ..INTO variable|OUTFILE|DUMPFILE */
if (lex->result != NULL) { if (lex->result != NULL) {
qtype = QUERY_TYPE_SESSION_WRITE; type = QUERY_TYPE_SESSION_WRITE;
goto return_qtype; goto return_qtype;
} }
/** /**
@ -407,9 +408,9 @@ static skygw_query_type_t resolve_query_type(
if (thd->variables.sql_log_bin == 0 && if (thd->variables.sql_log_bin == 0 &&
force_data_modify_op_replication) force_data_modify_op_replication)
{ {
qtype = QUERY_TYPE_SESSION_WRITE; type |= QUERY_TYPE_SESSION_WRITE;
} else { } else {
qtype = QUERY_TYPE_WRITE; type |= QUERY_TYPE_WRITE;
} }
goto return_qtype; goto return_qtype;
@ -422,11 +423,11 @@ static skygw_query_type_t resolve_query_type(
if (sql_command_flags[lex->sql_command] & CF_AUTO_COMMIT_TRANS) { if (sql_command_flags[lex->sql_command] & CF_AUTO_COMMIT_TRANS) {
if (lex->option_type == OPT_GLOBAL) if (lex->option_type == OPT_GLOBAL)
{ {
qtype = QUERY_TYPE_GLOBAL_WRITE; type |= (QUERY_TYPE_GLOBAL_WRITE|QUERY_TYPE_COMMIT);
} }
else else
{ {
qtype = QUERY_TYPE_SESSION_WRITE; type |= (QUERY_TYPE_SESSION_WRITE|QUERY_TYPE_COMMIT);
} }
goto return_qtype; goto return_qtype;
} }
@ -436,34 +437,34 @@ static skygw_query_type_t resolve_query_type(
case SQLCOM_SET_OPTION: case SQLCOM_SET_OPTION:
if (lex->option_type == OPT_GLOBAL) if (lex->option_type == OPT_GLOBAL)
{ {
qtype = QUERY_TYPE_GLOBAL_WRITE; type |= QUERY_TYPE_GLOBAL_WRITE;
break; break;
} }
/**<! fall through */ /**<! fall through */
case SQLCOM_CHANGE_DB: case SQLCOM_CHANGE_DB:
qtype = QUERY_TYPE_SESSION_WRITE; type |= QUERY_TYPE_SESSION_WRITE;
break; break;
case SQLCOM_SELECT: case SQLCOM_SELECT:
qtype = QUERY_TYPE_READ; type |= QUERY_TYPE_READ;
break; break;
case SQLCOM_CALL: case SQLCOM_CALL:
qtype = QUERY_TYPE_WRITE; type |= QUERY_TYPE_WRITE;
break; break;
case SQLCOM_BEGIN: case SQLCOM_BEGIN:
qtype = QUERY_TYPE_BEGIN_TRX; type |= QUERY_TYPE_BEGIN_TRX;
goto return_qtype; goto return_qtype;
break; break;
case SQLCOM_COMMIT: case SQLCOM_COMMIT:
qtype = QUERY_TYPE_COMMIT; type |= QUERY_TYPE_COMMIT;
goto return_qtype; goto return_qtype;
break; break;
case SQLCOM_ROLLBACK: case SQLCOM_ROLLBACK:
qtype = QUERY_TYPE_ROLLBACK; type |= QUERY_TYPE_ROLLBACK;
goto return_qtype; goto return_qtype;
break; break;
@ -471,7 +472,7 @@ static skygw_query_type_t resolve_query_type(
break; break;
} }
if (QTYPE_LESS_RESTRICTIVE_THAN_WRITE(qtype)) { if (QTYPE_LESS_RESTRICTIVE_THAN_WRITE(type)) {
/** /**
* These values won't change qtype more restrictive than write. * These values won't change qtype more restrictive than write.
* UDFs and procedures could possibly cause session-wide write, * UDFs and procedures could possibly cause session-wide write,
@ -500,8 +501,7 @@ static skygw_query_type_t resolve_query_type(
if (itype == Item::SUBSELECT_ITEM) { if (itype == Item::SUBSELECT_ITEM) {
continue; continue;
} else if (itype == Item::FUNC_ITEM) { } else if (itype == Item::FUNC_ITEM) {
skygw_query_type_t int func_qtype = QUERY_TYPE_UNKNOWN;
func_qtype = QUERY_TYPE_UNKNOWN;
/** /**
* Item types: * Item types:
* FIELD_ITEM = 0, FUNC_ITEM, * FIELD_ITEM = 0, FUNC_ITEM,
@ -554,7 +554,7 @@ static skygw_query_type_t resolve_query_type(
* An unknown (for maxscale) function / sp * An unknown (for maxscale) function / sp
* belongs to this category. * belongs to this category.
*/ */
func_qtype = QUERY_TYPE_WRITE; func_qtype |= QUERY_TYPE_WRITE;
LOGIF(LD, (skygw_log_write( LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG, LOGFILE_DEBUG,
"%lu [resolve_query_type] " "%lu [resolve_query_type] "
@ -564,7 +564,7 @@ static skygw_query_type_t resolve_query_type(
pthread_self()))); pthread_self())));
break; break;
case Item_func::UDF_FUNC: case Item_func::UDF_FUNC:
func_qtype = QUERY_TYPE_WRITE; func_qtype |= QUERY_TYPE_WRITE;
LOGIF(LD, (skygw_log_write( LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG, LOGFILE_DEBUG,
"%lu [resolve_query_type] " "%lu [resolve_query_type] "
@ -574,7 +574,7 @@ static skygw_query_type_t resolve_query_type(
break; break;
case Item_func::NOW_FUNC: case Item_func::NOW_FUNC:
case Item_func::GSYSVAR_FUNC: case Item_func::GSYSVAR_FUNC:
func_qtype = QUERY_TYPE_LOCAL_READ; func_qtype |= QUERY_TYPE_LOCAL_READ;
LOGIF(LD, (skygw_log_write( LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG, LOGFILE_DEBUG,
"%lu [resolve_query_type] " "%lu [resolve_query_type] "
@ -583,7 +583,7 @@ static skygw_query_type_t resolve_query_type(
pthread_self()))); pthread_self())));
break; break;
case Item_func::UNKNOWN_FUNC: case Item_func::UNKNOWN_FUNC:
func_qtype = QUERY_TYPE_READ; func_qtype |= QUERY_TYPE_READ;
/** /**
* Many built-in functions are of this * Many built-in functions are of this
* type, for example, rand(), soundex(), * type, for example, rand(), soundex(),
@ -607,17 +607,18 @@ static skygw_query_type_t resolve_query_type(
break; break;
} /**< switch */ } /**< switch */
/**< Set new query type */ /**< Set new query type */
qtype = set_query_type(&qtype, func_qtype); type |= set_query_type(&type, func_qtype);
} }
/** /**
* Write is as restrictive as it gets due functions, * Write is as restrictive as it gets due functions,
* so break. * so break.
*/ */
if (qtype == QUERY_TYPE_WRITE) { if ((type & QUERY_TYPE_WRITE) == QUERY_TYPE_WRITE) {
break; break;
} }
} /**< for */ } /**< for */
} /**< if */ } /**< if */
return_qtype: return_qtype:
qtype = (skygw_query_type_t)type;
return qtype; return qtype;
} }

View File

@ -29,18 +29,18 @@ EXTERN_C_BLOCK_BEGIN
* is modified * is modified
*/ */
typedef enum { typedef enum {
QUERY_TYPE_UNKNOWN = 7, /*< Couln't find out or parse error */ QUERY_TYPE_UNKNOWN = 0, /*< Couln't find out or parse error */
QUERY_TYPE_LOCAL_READ, /*< Read non-database data, execute in MaxScale */ QUERY_TYPE_LOCAL_READ = (1<<0), /*< Read non-database data, execute in MaxScale */
QUERY_TYPE_READ, /*< No updates */ QUERY_TYPE_READ = (1<<1), /*< No updates */
QUERY_TYPE_WRITE, /*< Master data will be modified */ QUERY_TYPE_WRITE = (1<<2), /*< Master data will be modified */
QUERY_TYPE_SESSION_WRITE,/*< Session data will be modified */ QUERY_TYPE_SESSION_WRITE = (1<<3), /*< Session data will be modified */
QUERY_TYPE_GLOBAL_WRITE, /*< Global system variable modification */ QUERY_TYPE_GLOBAL_WRITE = (1<<4), /*< Global system variable modification */
QUERY_TYPE_BEGIN_TRX, /*< BEGIN or START TRANSACTION */ QUERY_TYPE_BEGIN_TRX = (1<<5), /*< BEGIN or START TRANSACTION */
QUERY_TYPE_ROLLBACK, /*< ROLLBACK */ QUERY_TYPE_ROLLBACK = (1<<6), /*< ROLLBACK */
QUERY_TYPE_COMMIT /*< COMMIT */ QUERY_TYPE_COMMIT = (1<<7), /*< COMMIT */
} skygw_query_type_t; } skygw_query_type_t;
#define QUERY_IS_TYPE(mask,type) ((mask & type) == type)
skygw_query_type_t skygw_query_classifier_get_type( skygw_query_type_t skygw_query_classifier_get_type(
const char* query_str, const char* query_str,

View File

@ -724,6 +724,13 @@ static int routeQuery(
break; break;
case QUERY_TYPE_SESSION_WRITE: case QUERY_TYPE_SESSION_WRITE:
case (QUERY_TYPE_SESSION_WRITE|QUERY_TYPE_COMMIT):
if (QUERY_IS_TYPE(qtype,QUERY_TYPE_COMMIT) &&
transaction_active)
)
{
transaction_active = false;
}
/** /**
* Execute in backends used by current router session. * Execute in backends used by current router session.
* Save session variable commands to router session property * Save session variable commands to router session property
@ -759,7 +766,7 @@ static int routeQuery(
int rc2; int rc2;
rc = master_dcb->func.write(master_dcb, gwbuf_clone(querybuf)); rc = master_dcb->func.write(master_dcb, gwbuf_clone(querybuf));
rc2 = slave_dcb->func.write(slave_dcb, gwbuf_clone(querybuf)); rc2 = slave_dcb->func.write(slave_dcb, querybuf);
if (rc == 1 && rc == rc2) if (rc == 1 && rc == rc2)
{ {
@ -869,6 +876,10 @@ return_ret:
{ {
gwbuf_free(plainsqlbuf); gwbuf_free(plainsqlbuf);
} }
if (querystr != NULL)
{
free(querystr);
}
return ret; return ret;
} }