Merge pull request #31949 from Algunenano/parser_speedup

Speedup query parsing
This commit is contained in:
Maksim Kita 2021-12-05 16:24:45 +03:00 committed by GitHub
commit 4077d769e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 5947 additions and 24 deletions

View File

@ -1,7 +1,7 @@
#pragma once
#include <set>
#include <memory>
#include <vector>
#include <Core/Defines.h>
#include <Parsers/IAST_fwd.h>
@ -25,22 +25,24 @@ namespace ErrorCodes
struct Expected
{
const char * max_parsed_pos = nullptr;
std::set<const char *> variants;
std::vector<const char *> variants;
/// 'description' should be statically allocated string.
void add(const char * current_pos, const char * description)
ALWAYS_INLINE void add(const char * current_pos, const char * description)
{
if (!max_parsed_pos || current_pos > max_parsed_pos)
{
variants.clear();
max_parsed_pos = current_pos;
variants.push_back(description);
return;
}
if (!max_parsed_pos || current_pos >= max_parsed_pos)
variants.insert(description);
if ((current_pos == max_parsed_pos) && (find(variants.begin(), variants.end(), description) == variants.end()))
variants.push_back(description);
}
void add(TokenIterator it, const char * description)
ALWAYS_INLINE void add(TokenIterator it, const char * description)
{
add(it->begin, description);
}
@ -60,18 +62,18 @@ public:
Pos(Tokens & tokens_, uint32_t max_depth_) : TokenIterator(tokens_), max_depth(max_depth_) {}
void increaseDepth()
ALWAYS_INLINE void increaseDepth()
{
++depth;
if (max_depth > 0 && depth > max_depth)
if (unlikely(max_depth > 0 && depth > max_depth))
throw Exception(
"Maximum parse depth (" + std::to_string(max_depth) + ") exceeded. Consider rising max_parser_depth parameter.",
ErrorCodes::TOO_DEEP_RECURSION);
}
void decreaseDepth()
ALWAYS_INLINE void decreaseDepth()
{
if (depth == 0)
if (unlikely(depth == 0))
throw Exception("Logical error in parser: incorrect calculation of parse depth", ErrorCodes::LOGICAL_ERROR);
--depth;
}

View File

@ -12,7 +12,7 @@ class IParserBase : public IParser
{
public:
template <typename F>
static bool wrapParseImpl(Pos & pos, const F & func)
ALWAYS_INLINE static bool wrapParseImpl(Pos & pos, const F & func)
{
Pos begin = pos;
bool res = func();
@ -24,7 +24,7 @@ public:
struct IncreaseDepthTag {};
template <typename F>
static bool wrapParseImpl(Pos & pos, IncreaseDepthTag, const F & func)
ALWAYS_INLINE static bool wrapParseImpl(Pos & pos, IncreaseDepthTag, const F & func)
{
Pos begin = pos;
pos.increaseDepth();

View File

@ -1,8 +1,10 @@
#pragma once
#include <vector>
#include <Core/Defines.h>
#include <Parsers/Lexer.h>
#include <vector>
namespace DB
{
@ -59,22 +61,30 @@ private:
public:
explicit TokenIterator(Tokens & tokens_) : tokens(&tokens_) {}
const Token & get() { return (*tokens)[index]; }
const Token & operator*() { return get(); }
const Token * operator->() { return &get(); }
ALWAYS_INLINE const Token & get() { return (*tokens)[index]; }
ALWAYS_INLINE const Token & operator*() { return get(); }
ALWAYS_INLINE const Token * operator->() { return &get(); }
TokenIterator & operator++() { ++index; return *this; }
TokenIterator & operator--() { --index; return *this; }
ALWAYS_INLINE TokenIterator & operator++()
{
++index;
return *this;
}
ALWAYS_INLINE TokenIterator & operator--()
{
--index;
return *this;
}
bool operator< (const TokenIterator & rhs) const { return index < rhs.index; }
bool operator<= (const TokenIterator & rhs) const { return index <= rhs.index; }
bool operator== (const TokenIterator & rhs) const { return index == rhs.index; }
bool operator!= (const TokenIterator & rhs) const { return index != rhs.index; }
ALWAYS_INLINE bool operator<(const TokenIterator & rhs) const { return index < rhs.index; }
ALWAYS_INLINE bool operator<=(const TokenIterator & rhs) const { return index <= rhs.index; }
ALWAYS_INLINE bool operator==(const TokenIterator & rhs) const { return index == rhs.index; }
ALWAYS_INLINE bool operator!=(const TokenIterator & rhs) const { return index != rhs.index; }
bool isValid() { return get().type < TokenType::EndOfStream; }
ALWAYS_INLINE bool isValid() { return get().type < TokenType::EndOfStream; }
/// Rightmost token we had looked.
const Token & max() { return tokens->max(); }
ALWAYS_INLINE const Token & max() { return tokens->max(); }
};

File diff suppressed because it is too large Load Diff