diff --git a/server/modules/filter/hintfilter/hintfilter.cc b/server/modules/filter/hintfilter/hintfilter.cc index dc7f555af..e4fb5bd44 100644 --- a/server/modules/filter/hintfilter/hintfilter.cc +++ b/server/modules/filter/hintfilter/hintfilter.cc @@ -206,15 +206,11 @@ static int routeQuery(MXS_FILTER* instance, MXS_FILTER_SESSION* session, GWBUF* { HINT_SESSION* my_session = (HINT_SESSION*)session; - if (modutil_is_SQL(queue)) + if (modutil_is_SQL(queue) && gwbuf_length(queue) > 5) { my_session->request = NULL; my_session->query_len = 0; - HINT* new_hint = hint_parser(my_session, queue); - if (new_hint) - { - queue->hint = hint_splice(queue->hint, new_hint); - } + process_hints(my_session, queue); } /* Now process the request */ diff --git a/server/modules/filter/hintfilter/hintparser.cc b/server/modules/filter/hintfilter/hintparser.cc index 46d282045..b8ee98a18 100644 --- a/server/modules/filter/hintfilter/hintparser.cc +++ b/server/modules/filter/hintfilter/hintparser.cc @@ -953,6 +953,22 @@ struct Token TOKEN_VALUE type; }; +static const std::unordered_map tokens +{ + {"begin", TOK_START}, + {"end", TOK_STOP}, + {"last", TOK_LAST}, + {"master", TOK_MASTER}, + {"maxscale", TOK_MAXSCALE}, + {"prepare", TOK_PREPARE}, + {"route", TOK_ROUTE}, + {"server", TOK_SERVER}, + {"slave", TOK_SLAVE}, + {"start", TOK_START}, + {"stop", TOK_STOP}, + {"to", TOK_TO}, +}; + /** * Extract the next token * @@ -962,23 +978,9 @@ struct Token * @return The next token */ template -Token next_token(InputIter& it, InputIter end) +Token next_token(InputIter* iter, InputIter end) { - const std::unordered_map tokens - { - {"begin", TOK_START}, - {"end", TOK_STOP}, - {"last", TOK_LAST}, - {"master", TOK_MASTER}, - {"maxscale", TOK_MAXSCALE}, - {"prepare", TOK_PREPARE}, - {"route", TOK_ROUTE}, - {"server", TOK_SERVER}, - {"slave", TOK_SLAVE}, - {"start", TOK_START}, - {"stop", TOK_STOP}, - {"to", TOK_TO}, - }; + InputIter& it = *iter; while (it != end && isspace(*it)) { @@ -1032,13 +1034,13 @@ template HINT* process_definition(InputIter it, InputIter end) { HINT* rval = nullptr; - auto t = next_token(it, end); + auto t = next_token(&it, end); if (t.type == TOK_ROUTE) { - if (next_token(it, end).type == TOK_TO) + if (next_token(&it, end).type == TOK_TO) { - t = next_token(it, end); + t = next_token(&it, end); if (t.type == TOK_MASTER) { @@ -1054,7 +1056,7 @@ HINT* process_definition(InputIter it, InputIter end) } else if (t.type == TOK_SERVER) { - t = next_token(it, end); + t = next_token(&it, end); if (t.type == TOK_STRING) { @@ -1067,8 +1069,8 @@ HINT* process_definition(InputIter it, InputIter end) else if (t.type == TOK_STRING) { std::string key(t.begin, t.end); - auto eq = next_token(it, end); - auto val = next_token(it, end); + auto eq = next_token(&it, end); + auto val = next_token(&it, end); if (eq.type == TOK_EQUAL && val.type == TOK_STRING) { @@ -1077,7 +1079,7 @@ HINT* process_definition(InputIter it, InputIter end) } } - if (rval && next_token(it, end).type != TOK_END) + if (rval && next_token(&it, end).type != TOK_END) { // Unexpected input after hint definition, treat it as an error and remove the hint hint_free(rval); @@ -1092,17 +1094,17 @@ HINT* process_comment(HINT_SESSION* session, InputIter it, InputIter end) { HINT* rval = nullptr; - if (next_token(it, end).type == TOK_MAXSCALE) + if (next_token(&it, end).type == TOK_MAXSCALE) { // Peek at the next token auto prev_it = it; - auto t = next_token(it, end); + auto t = next_token(&it, end); if (t.type == TOK_START) { if ((rval = process_definition(it, end))) { - hint_push(session, rval); + hint_push(session, hint_dup(rval)); } } else if (t.type == TOK_STOP) @@ -1112,11 +1114,11 @@ HINT* process_comment(HINT_SESSION* session, InputIter it, InputIter end) else if (t.type == TOK_STRING) { std::string key(t.begin, t.end); - t = next_token(it, end); + t = next_token(&it, end); if (t.type == TOK_EQUAL) { - t = next_token(it, end); + t = next_token(&it, end); if (t.type == TOK_STRING) { @@ -1127,10 +1129,12 @@ HINT* process_comment(HINT_SESSION* session, InputIter it, InputIter end) } else if (t.type == TOK_PREPARE) { - if ((rval = process_definition(it, end))) + HINT* hint = process_definition(it, end); + + if (hint) { // Preparation of a named hint - create_named_hint(session, key.c_str(), rval); + create_named_hint(session, key.c_str(), hint); } } else if (t.type == TOK_START) @@ -1144,10 +1148,16 @@ HINT* process_comment(HINT_SESSION* session, InputIter it, InputIter end) hint_push(session, hint_dup(rval)); } } - else if ((rval = lookup_named_hint(session, key.c_str()))) + else if (next_token(&it, end).type == TOK_END) { - // We starting an already define named hint - hint_push(session, hint_dup(rval)); + HINT* hint = lookup_named_hint(session, key.c_str()); + + if (hint) + { + // We're starting an already define named hint + hint_push(session, hint_dup(hint)); + rval = hint_dup(hint); + } } } } @@ -1160,3 +1170,25 @@ HINT* process_comment(HINT_SESSION* session, InputIter it, InputIter end) return rval; } + +void process_hints(HINT_SESSION* session, GWBUF* buffer) +{ + mxs::Buffer buf(buffer); + + for (auto comment : get_all_comments(std::next(buf.begin(), 5), buf.end())) + { + HINT* hint = process_comment(session, comment.first, comment.second); + + if (hint) + { + buffer->hint = hint_splice(buffer->hint, hint); + } + } + + if (!buffer->hint && session->stack) + { + buffer->hint = hint_dup(session->stack->hint); + } + + buf.release(); +} diff --git a/server/modules/filter/hintfilter/mysqlhint.hh b/server/modules/filter/hintfilter/mysqlhint.hh index 9c48979e0..9718147b3 100644 --- a/server/modules/filter/hintfilter/mysqlhint.hh +++ b/server/modules/filter/hintfilter/mysqlhint.hh @@ -107,5 +107,6 @@ typedef struct extern HINT* hint_parser(HINT_SESSION* session, GWBUF* request); NAMEDHINTS* free_named_hint(NAMEDHINTS* named_hint); HINTSTACK* free_hint_stack(HINTSTACK* hint_stack); +void process_hints(HINT_SESSION* session, GWBUF* buffer); MXS_END_DECLS