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:
Johan Wikman
2017-03-14 17:13:46 +02:00
parent 470de51e22
commit c2add97e30
2 changed files with 136 additions and 15 deletions

View File

@ -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
MXS_NOTICE("Transaction tracking: In statement '%.*s', unexpected token at '%.*s'.",
(int)m_len, m_pSql, (int)(m_pEnd - m_pI), m_pI); (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,17 +290,14 @@ private:
return type_mask; return type_mask;
} }
uint32_t parse_set(uint32_t type_mask) uint32_t parse_set_autocommit(uint32_t type_mask)
{ {
token_t token = next_token(TOKEN_REQUIRED); token_t token = next_token(TOKEN_REQUIRED);
switch (token) switch (token)
{ {
case TK_AUTOCOMMIT: case TK_EQ:
token = next_token(); token = next_token(TOKEN_REQUIRED);
if (token == TK_EQ)
{
token = next_token();
if (token == TK_ONE || token == TK_TRUE) if (token == TK_ONE || token == TK_TRUE)
{ {
type_mask |= (QUERY_TYPE_COMMIT | QUERY_TYPE_ENABLE_AUTOCOMMIT); type_mask |= (QUERY_TYPE_COMMIT | QUERY_TYPE_ENABLE_AUTOCOMMIT);
@ -305,13 +309,79 @@ private:
else else
{ {
type_mask = 0; type_mask = 0;
if (token != PARSER_EXHAUSTED)
{
log_unexpected(); 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)
{
token_t token = next_token(TOKEN_REQUIRED);
switch (token)
{
case TK_AUTOCOMMIT:
type_mask = parse_set_autocommit(type_mask);
break;
case TK_GLOBAL:
case TK_SESSION:
token = next_token(TOKEN_REQUIRED);
if (token == TK_AUTOCOMMIT)
{
type_mask = parse_set_autocommit(type_mask);
}
else
{
type_mask = 0;
if (token != PARSER_EXHAUSTED)
{
log_unexpected();
}
}
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 = parse_set_autocommit(type_mask);
}
else
{
type_mask = 0;
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':
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); token = expect_token(TBP_EXPECT_TOKEN("only"), TK_ONLY);
}
}
break; break;
case 'r': case 'r':
@ -698,9 +807,16 @@ private:
case 's': case 's':
case 'S': case 'S':
if (is_next_char('e') || is_next_char('E')) if (is_next_char('e') || is_next_char('E'))
{
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); 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'))
{ {
token = expect_token(TBP_EXPECT_TOKEN("snapshot"), TK_SNAPSHOT); token = expect_token(TBP_EXPECT_TOKEN("snapshot"), TK_SNAPSHOT);

View File

@ -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]);