Recognise various autocommit syntaxes
set autocommit=1 set global autocommit=1 set session autocommit=1 set @@global.autocommit=1 set @@session.autocommit=1
This commit is contained in:
@ -41,12 +41,17 @@ public:
|
|||||||
TK_COMMA,
|
TK_COMMA,
|
||||||
TK_COMMIT,
|
TK_COMMIT,
|
||||||
TK_CONSISTENT,
|
TK_CONSISTENT,
|
||||||
|
TK_DOT,
|
||||||
TK_EQ,
|
TK_EQ,
|
||||||
TK_FALSE,
|
TK_FALSE,
|
||||||
|
TK_GLOBAL,
|
||||||
|
TK_GLOBAL_VAR,
|
||||||
TK_ONE,
|
TK_ONE,
|
||||||
TK_ONLY,
|
TK_ONLY,
|
||||||
TK_READ,
|
TK_READ,
|
||||||
TK_ROLLBACK,
|
TK_ROLLBACK,
|
||||||
|
TK_SESSION,
|
||||||
|
TK_SESSION_VAR,
|
||||||
TK_SET,
|
TK_SET,
|
||||||
TK_SNAPSHOT,
|
TK_SNAPSHOT,
|
||||||
TK_START,
|
TK_START,
|
||||||
@ -119,14 +124,16 @@ private:
|
|||||||
|
|
||||||
void log_unexpected()
|
void log_unexpected()
|
||||||
{
|
{
|
||||||
MXS_ERROR("In statement '%.*s', unexpected token at '%.*s'.",
|
#ifdef SS_DEBUG
|
||||||
(int)m_len, m_pSql, (int)(m_pEnd - m_pI), m_pI);
|
MXS_NOTICE("Transaction tracking: In statement '%.*s', unexpected token at '%.*s'.",
|
||||||
|
(int)m_len, m_pSql, (int)(m_pEnd - m_pI), m_pI);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_exhausted()
|
void log_exhausted()
|
||||||
{
|
{
|
||||||
#ifdef SS_DEBUG
|
#ifdef SS_DEBUG
|
||||||
MXS_WARNING("More tokens expected in statement '%.*s'.", (int)m_len, m_pSql);
|
MXS_NOTICE("Transaction tracking: More tokens expected in statement '%.*s'.", (int)m_len, m_pSql);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,6 +290,45 @@ private:
|
|||||||
return type_mask;
|
return type_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t parse_set_autocommit(uint32_t type_mask)
|
||||||
|
{
|
||||||
|
token_t token = next_token(TOKEN_REQUIRED);
|
||||||
|
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case TK_EQ:
|
||||||
|
token = next_token(TOKEN_REQUIRED);
|
||||||
|
if (token == TK_ONE || token == TK_TRUE)
|
||||||
|
{
|
||||||
|
type_mask |= (QUERY_TYPE_COMMIT | QUERY_TYPE_ENABLE_AUTOCOMMIT);
|
||||||
|
}
|
||||||
|
else if (token == TK_ZERO || token == TK_FALSE)
|
||||||
|
{
|
||||||
|
type_mask = (QUERY_TYPE_BEGIN_TRX | QUERY_TYPE_DISABLE_AUTOCOMMIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type_mask = 0;
|
||||||
|
|
||||||
|
if (token != PARSER_EXHAUSTED)
|
||||||
|
{
|
||||||
|
log_unexpected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARSER_EXHAUSTED:
|
||||||
|
type_mask = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
type_mask = 0;
|
||||||
|
log_unexpected();
|
||||||
|
}
|
||||||
|
|
||||||
|
return type_mask;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t parse_set(uint32_t type_mask)
|
uint32_t parse_set(uint32_t type_mask)
|
||||||
{
|
{
|
||||||
token_t token = next_token(TOKEN_REQUIRED);
|
token_t token = next_token(TOKEN_REQUIRED);
|
||||||
@ -290,28 +336,52 @@ private:
|
|||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
case TK_AUTOCOMMIT:
|
case TK_AUTOCOMMIT:
|
||||||
token = next_token();
|
type_mask = parse_set_autocommit(type_mask);
|
||||||
if (token == TK_EQ)
|
break;
|
||||||
|
|
||||||
|
case TK_GLOBAL:
|
||||||
|
case TK_SESSION:
|
||||||
|
token = next_token(TOKEN_REQUIRED);
|
||||||
|
if (token == TK_AUTOCOMMIT)
|
||||||
{
|
{
|
||||||
token = next_token();
|
type_mask = parse_set_autocommit(type_mask);
|
||||||
if (token == TK_ONE || token == TK_TRUE)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type_mask = 0;
|
||||||
|
if (token != PARSER_EXHAUSTED)
|
||||||
{
|
{
|
||||||
type_mask |= (QUERY_TYPE_COMMIT | QUERY_TYPE_ENABLE_AUTOCOMMIT);
|
log_unexpected();
|
||||||
}
|
}
|
||||||
else if (token == TK_ZERO || token == TK_FALSE)
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_GLOBAL_VAR:
|
||||||
|
case TK_SESSION_VAR:
|
||||||
|
token = next_token(TOKEN_REQUIRED);
|
||||||
|
if (token == TK_DOT)
|
||||||
|
{
|
||||||
|
token = next_token(TOKEN_REQUIRED);
|
||||||
|
if (token == TK_AUTOCOMMIT)
|
||||||
{
|
{
|
||||||
type_mask = (QUERY_TYPE_BEGIN_TRX | QUERY_TYPE_DISABLE_AUTOCOMMIT);
|
type_mask = parse_set_autocommit(type_mask);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type_mask = 0;
|
type_mask = 0;
|
||||||
log_unexpected();
|
if (token != PARSER_EXHAUSTED)
|
||||||
|
{
|
||||||
|
log_unexpected();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type_mask = 0;
|
type_mask = 0;
|
||||||
MXS_WARNING("Expected more.");
|
if (token != PARSER_EXHAUSTED)
|
||||||
|
{
|
||||||
|
log_unexpected();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -468,7 +538,7 @@ private:
|
|||||||
{
|
{
|
||||||
const char* pNext = m_pI;
|
const char* pNext = m_pI;
|
||||||
|
|
||||||
while ((pNext < m_pEnd) && isalpha(*pNext))
|
while ((pNext < m_pEnd) && (isalpha(*pNext) || (*pNext == '@')))
|
||||||
{
|
{
|
||||||
++pNext;
|
++pNext;
|
||||||
}
|
}
|
||||||
@ -627,6 +697,21 @@ private:
|
|||||||
{
|
{
|
||||||
switch (*m_pI)
|
switch (*m_pI)
|
||||||
{
|
{
|
||||||
|
case '@':
|
||||||
|
if (is_next_char('a', 2) || is_next_char('A', 2))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("@@autocommit"), TK_AUTOCOMMIT);
|
||||||
|
}
|
||||||
|
if (is_next_char('s', 2) || is_next_char('S', 2))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("@@session"), TK_SESSION_VAR);
|
||||||
|
}
|
||||||
|
else if (is_next_char('g', 2) || is_next_char('G', 2))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("@@global"), TK_GLOBAL_VAR);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'A':
|
case 'A':
|
||||||
token = expect_token(TBP_EXPECT_TOKEN("autocommit"), TK_AUTOCOMMIT);
|
token = expect_token(TBP_EXPECT_TOKEN("autocommit"), TK_AUTOCOMMIT);
|
||||||
@ -657,6 +742,11 @@ private:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
++m_pI;
|
||||||
|
token = TK_DOT;
|
||||||
|
break;
|
||||||
|
|
||||||
case '=':
|
case '=':
|
||||||
++m_pI;
|
++m_pI;
|
||||||
token = TK_EQ;
|
token = TK_EQ;
|
||||||
@ -667,6 +757,11 @@ private:
|
|||||||
token = expect_token(TBP_EXPECT_TOKEN("false"), TK_FALSE);
|
token = expect_token(TBP_EXPECT_TOKEN("false"), TK_FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("global"), TK_GLOBAL);
|
||||||
|
break;
|
||||||
|
|
||||||
case '1':
|
case '1':
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
@ -680,7 +775,21 @@ private:
|
|||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'O':
|
case 'O':
|
||||||
token = expect_token(TBP_EXPECT_TOKEN("only"), TK_ONLY);
|
if (is_next_char('f') || is_next_char('F'))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("off"), TK_ZERO);
|
||||||
|
}
|
||||||
|
else if (is_next_char('n') || is_next_char('N'))
|
||||||
|
{
|
||||||
|
if (is_next_char('l') || is_next_char('L'))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("on"), TK_ONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("only"), TK_ONLY);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
@ -699,7 +808,14 @@ private:
|
|||||||
case 'S':
|
case 'S':
|
||||||
if (is_next_char('e') || is_next_char('E'))
|
if (is_next_char('e') || is_next_char('E'))
|
||||||
{
|
{
|
||||||
token = expect_token(TBP_EXPECT_TOKEN("set"), TK_SET);
|
if (is_next_char('s', 2) || is_next_char('S', 2))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("session"), TK_SESSION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("set"), TK_SET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (is_next_char('n') || is_next_char('N'))
|
else if (is_next_char('n') || is_next_char('N'))
|
||||||
{
|
{
|
||||||
|
@ -100,6 +100,11 @@ struct test_case
|
|||||||
{ "SET AUTOCOMMIT=false", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
{ "SET AUTOCOMMIT=false", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
||||||
|
|
||||||
{ "SET AUTOCOMMIT=0", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
{ "SET AUTOCOMMIT=0", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
||||||
|
{ "SET @@AUTOCOMMIT=0", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
||||||
|
{ "SET GLOBAL AUTOCOMMIT=0", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
||||||
|
{ "SET SESSION AUTOCOMMIT=0", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
||||||
|
{ "SET @@SESSION . AUTOCOMMIT=0", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
||||||
|
{ "SET @@GLOBAL . AUTOCOMMIT=0", QUERY_TYPE_BEGIN_TRX|QUERY_TYPE_DISABLE_AUTOCOMMIT },
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t N_TEST_CASES = sizeof(test_cases)/sizeof(test_cases[0]);
|
const size_t N_TEST_CASES = sizeof(test_cases)/sizeof(test_cases[0]);
|
||||||
|
Reference in New Issue
Block a user