Handle WITH CONSISTENT SNAPSHOT as well
TrsBoundaryParser now capable of parsing WITH CONSISTENT SNAPSHOT transaction statements as well.
This commit is contained in:
@ -38,7 +38,9 @@ public:
|
|||||||
{
|
{
|
||||||
TK_AUTOCOMMIT,
|
TK_AUTOCOMMIT,
|
||||||
TK_BEGIN,
|
TK_BEGIN,
|
||||||
|
TK_COMMA,
|
||||||
TK_COMMIT,
|
TK_COMMIT,
|
||||||
|
TK_CONSISTENT,
|
||||||
TK_EQ,
|
TK_EQ,
|
||||||
TK_FALSE,
|
TK_FALSE,
|
||||||
TK_ONE,
|
TK_ONE,
|
||||||
@ -46,9 +48,11 @@ public:
|
|||||||
TK_READ,
|
TK_READ,
|
||||||
TK_ROLLBACK,
|
TK_ROLLBACK,
|
||||||
TK_SET,
|
TK_SET,
|
||||||
|
TK_SNAPSHOT,
|
||||||
TK_START,
|
TK_START,
|
||||||
TK_TRANSACTION,
|
TK_TRANSACTION,
|
||||||
TK_TRUE,
|
TK_TRUE,
|
||||||
|
TK_WITH,
|
||||||
TK_WORK,
|
TK_WORK,
|
||||||
TK_WRITE,
|
TK_WRITE,
|
||||||
TK_ZERO,
|
TK_ZERO,
|
||||||
@ -105,12 +109,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum token_required_t
|
||||||
|
{
|
||||||
|
TOKEN_REQUIRED,
|
||||||
|
TOKEN_NOT_REQUIRED,
|
||||||
|
};
|
||||||
|
|
||||||
void log_unexpected()
|
void log_unexpected()
|
||||||
{
|
{
|
||||||
MXS_ERROR("In statement '%.*s', unexpected token at '%.*s'.",
|
MXS_ERROR("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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void log_exhausted()
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
MXS_WARNING("More tokens expected in statement '%.*s'.", (int)m_len, m_pSql);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t parse()
|
uint32_t parse()
|
||||||
{
|
{
|
||||||
uint32_t type_mask = 0;
|
uint32_t type_mask = 0;
|
||||||
@ -200,6 +217,10 @@ private:
|
|||||||
|
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
|
case TK_COMMA:
|
||||||
|
type_mask = parse_transaction(type_mask);
|
||||||
|
break;
|
||||||
|
|
||||||
case PARSER_EXHAUSTED:
|
case PARSER_EXHAUSTED:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -213,7 +234,7 @@ private:
|
|||||||
|
|
||||||
uint32_t parse_read(uint32_t type_mask)
|
uint32_t parse_read(uint32_t type_mask)
|
||||||
{
|
{
|
||||||
token_t token = next_token();
|
token_t token = next_token(TOKEN_REQUIRED);
|
||||||
|
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
@ -227,7 +248,6 @@ private:
|
|||||||
|
|
||||||
case PARSER_EXHAUSTED:
|
case PARSER_EXHAUSTED:
|
||||||
type_mask = 0;
|
type_mask = 0;
|
||||||
MXS_WARNING("Expected more.");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -263,7 +283,7 @@ private:
|
|||||||
|
|
||||||
uint32_t parse_set(uint32_t type_mask)
|
uint32_t parse_set(uint32_t type_mask)
|
||||||
{
|
{
|
||||||
token_t token = next_token();
|
token_t token = next_token(TOKEN_REQUIRED);
|
||||||
|
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
@ -295,7 +315,6 @@ private:
|
|||||||
|
|
||||||
case PARSER_EXHAUSTED:
|
case PARSER_EXHAUSTED:
|
||||||
type_mask = 0;
|
type_mask = 0;
|
||||||
MXS_WARNING("Expected more.");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -308,7 +327,7 @@ private:
|
|||||||
|
|
||||||
uint32_t parse_start(uint32_t type_mask)
|
uint32_t parse_start(uint32_t type_mask)
|
||||||
{
|
{
|
||||||
token_t token = next_token();
|
token_t token = next_token(TOKEN_REQUIRED);
|
||||||
|
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
@ -318,7 +337,6 @@ private:
|
|||||||
|
|
||||||
case PARSER_EXHAUSTED:
|
case PARSER_EXHAUSTED:
|
||||||
type_mask = 0;
|
type_mask = 0;
|
||||||
MXS_WARNING("Expected more.");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -341,19 +359,52 @@ private:
|
|||||||
type_mask = parse_read(type_mask);
|
type_mask = parse_read(type_mask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TK_WITH:
|
||||||
|
type_mask = parse_with_consistent_snapshot(type_mask);
|
||||||
|
break;
|
||||||
|
|
||||||
case PARSER_EXHAUSTED:
|
case PARSER_EXHAUSTED:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MXS_WARNING("START TRANSACTION followed by '%.*s', assuming it's ok.",
|
type_mask = 0;
|
||||||
(int)(m_pEnd - m_pI), m_pI);
|
|
||||||
//type_mask = 0;
|
|
||||||
log_unexpected();
|
log_unexpected();
|
||||||
}
|
}
|
||||||
|
|
||||||
return type_mask;
|
return type_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t parse_with_consistent_snapshot(uint32_t type_mask)
|
||||||
|
{
|
||||||
|
token_t token = next_token(TOKEN_REQUIRED);
|
||||||
|
|
||||||
|
if (token == TK_CONSISTENT)
|
||||||
|
{
|
||||||
|
token = next_token(TOKEN_REQUIRED);
|
||||||
|
|
||||||
|
if (token == TK_SNAPSHOT)
|
||||||
|
{
|
||||||
|
token = next_token();
|
||||||
|
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case TK_COMMA:
|
||||||
|
type_mask = parse_transaction(type_mask);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARSER_EXHAUSTED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
type_mask = 0;
|
||||||
|
log_unexpected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type_mask;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t parse_work(uint32_t type_mask)
|
uint32_t parse_work(uint32_t type_mask)
|
||||||
{
|
{
|
||||||
token_t token = next_token();
|
token_t token = next_token();
|
||||||
@ -379,6 +430,10 @@ private:
|
|||||||
|
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
|
case TK_COMMA:
|
||||||
|
type_mask = parse_transaction(type_mask);
|
||||||
|
break;
|
||||||
|
|
||||||
case PARSER_EXHAUSTED:
|
case PARSER_EXHAUSTED:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -435,7 +490,7 @@ private:
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
token_t next_token()
|
token_t next_token(token_required_t required = TOKEN_NOT_REQUIRED)
|
||||||
{
|
{
|
||||||
token_t token = PARSER_UNKNOWN_TOKEN;
|
token_t token = PARSER_UNKNOWN_TOKEN;
|
||||||
|
|
||||||
@ -479,17 +534,29 @@ private:
|
|||||||
token = expect_token(TBP_EXPECT_TOKEN("begin"), TK_BEGIN);
|
token = expect_token(TBP_EXPECT_TOKEN("begin"), TK_BEGIN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
++m_pI;
|
||||||
|
token = TK_COMMA;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'C':
|
case 'C':
|
||||||
token = expect_token(TBP_EXPECT_TOKEN("commit"), TK_COMMIT);
|
if (is_next_char('o') || is_next_char('O'))
|
||||||
|
{
|
||||||
|
if (is_next_char('m', 2) || is_next_char('M', 2))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("commit"), TK_COMMIT);
|
||||||
|
}
|
||||||
|
else if (is_next_char('n', 2) || is_next_char('N', 2))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("consistent"), TK_CONSISTENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '=':
|
case '=':
|
||||||
if (!is_next_char('='))
|
++m_pI;
|
||||||
{
|
token = TK_EQ;
|
||||||
++m_pI;
|
|
||||||
token = TK_EQ;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
@ -531,6 +598,10 @@ private:
|
|||||||
{
|
{
|
||||||
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'))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("snapshot"), TK_SNAPSHOT);
|
||||||
|
}
|
||||||
else if (is_next_char('t') || is_next_char('T'))
|
else if (is_next_char('t') || is_next_char('T'))
|
||||||
{
|
{
|
||||||
token = expect_token(TBP_EXPECT_TOKEN("start"), TK_START);
|
token = expect_token(TBP_EXPECT_TOKEN("start"), TK_START);
|
||||||
@ -554,7 +625,11 @@ private:
|
|||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
case 'W':
|
case 'W':
|
||||||
if (is_next_char('o') || is_next_char('O'))
|
if (is_next_char('i') || is_next_char('I'))
|
||||||
|
{
|
||||||
|
token = expect_token(TBP_EXPECT_TOKEN("with"), TK_WITH);
|
||||||
|
}
|
||||||
|
else if (is_next_char('o') || is_next_char('O'))
|
||||||
{
|
{
|
||||||
token = expect_token(TBP_EXPECT_TOKEN("work"), TK_WORK);
|
token = expect_token(TBP_EXPECT_TOKEN("work"), TK_WORK);
|
||||||
}
|
}
|
||||||
@ -580,6 +655,11 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((token == PARSER_EXHAUSTED) && (required == TOKEN_REQUIRED))
|
||||||
|
{
|
||||||
|
log_exhausted();
|
||||||
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,11 @@ struct test_case
|
|||||||
{ "START TRANSACTION WITH CONSISTENT SNAPSHOT", QUERY_TYPE_BEGIN_TRX },
|
{ "START TRANSACTION WITH CONSISTENT SNAPSHOT", QUERY_TYPE_BEGIN_TRX },
|
||||||
{ "START TRANSACTION WITH CONSISTENT SNAPSHOT", QUERY_TYPE_BEGIN_TRX },
|
{ "START TRANSACTION WITH CONSISTENT SNAPSHOT", QUERY_TYPE_BEGIN_TRX },
|
||||||
|
|
||||||
|
{ "START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY", QUERY_TYPE_BEGIN_TRX | QUERY_TYPE_READ },
|
||||||
|
{ "START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT", QUERY_TYPE_BEGIN_TRX | QUERY_TYPE_READ },
|
||||||
|
{ "START TRANSACTION WITH CONSISTENT SNAPSHOT, READ WRITE", QUERY_TYPE_BEGIN_TRX | QUERY_TYPE_WRITE },
|
||||||
|
{ "START TRANSACTION READ WRITE, WITH CONSISTENT SNAPSHOT", QUERY_TYPE_BEGIN_TRX | QUERY_TYPE_WRITE },
|
||||||
|
|
||||||
{ "SET AUTOCOMMIT=true", QUERY_TYPE_COMMIT|QUERY_TYPE_ENABLE_AUTOCOMMIT },
|
{ "SET AUTOCOMMIT=true", QUERY_TYPE_COMMIT|QUERY_TYPE_ENABLE_AUTOCOMMIT },
|
||||||
{ "SET AUTOCOMMIT=true", QUERY_TYPE_COMMIT|QUERY_TYPE_ENABLE_AUTOCOMMIT },
|
{ "SET AUTOCOMMIT=true", QUERY_TYPE_COMMIT|QUERY_TYPE_ENABLE_AUTOCOMMIT },
|
||||||
{ "SET AUTOCOMMIT =true", QUERY_TYPE_COMMIT|QUERY_TYPE_ENABLE_AUTOCOMMIT },
|
{ "SET AUTOCOMMIT =true", QUERY_TYPE_COMMIT|QUERY_TYPE_ENABLE_AUTOCOMMIT },
|
||||||
|
Reference in New Issue
Block a user