ClickHouse/dbms/include/DB/Parsers/IAST.h

185 lines
5.7 KiB
C++
Raw Normal View History

2011-08-09 19:19:00 +00:00
#pragma once
2010-06-24 19:12:10 +00:00
#include <set>
#include <memory>
2017-01-17 18:03:32 +00:00
#include <ostream>
2010-06-24 19:12:10 +00:00
#include <DB/Core/Types.h>
2015-10-05 01:35:28 +00:00
#include <DB/Common/Exception.h>
2010-06-24 19:12:10 +00:00
#include <DB/Parsers/StringRange.h>
class SipHash;
2010-06-24 19:12:10 +00:00
namespace DB
{
namespace ErrorCodes
{
extern const int NOT_A_COLUMN;
extern const int UNKNOWN_TYPE_OF_AST_NODE;
extern const int UNKNOWN_ELEMENT_IN_AST;
}
using IdentifierNameSet = std::set<String>;
2010-06-24 19:12:10 +00:00
class IAST;
using ASTPtr = std::shared_ptr<IAST>;
using ASTs = std::vector<ASTPtr>;
class WriteBuffer;
2010-06-24 19:12:10 +00:00
/** Элемент синтаксического дерева (в дальнейшем - направленного ациклического графа с элементами семантики)
*/
class IAST
2011-08-13 21:05:18 +00:00
{
2010-06-24 19:12:10 +00:00
public:
2011-08-13 21:05:18 +00:00
ASTs children;
StringRange range;
2015-09-18 13:36:10 +00:00
2013-02-11 11:22:15 +00:00
/** Строка с полным запросом.
* Этот указатель не дает ее удалить, пока range в нее ссылается.
*/
StringPtr query_string;
2011-08-28 02:22:23 +00:00
2014-12-17 15:26:24 +00:00
IAST() = default;
IAST(const StringRange range_) : range(range_) {}
virtual ~IAST() = default;
2011-09-25 03:37:09 +00:00
/** Получить каноническое имя столбца, если элемент является столбцом */
virtual String getColumnName() const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::NOT_A_COLUMN); }
2011-11-06 04:21:09 +00:00
/** Получить алиас, если он есть, или каноническое имя столбца, если его нет. */
2014-07-03 22:39:13 +00:00
virtual String getAliasOrColumnName() const { return getColumnName(); }
/** Получить алиас, если он есть, или пустую строку, если его нет, или если элемент не поддерживает алиасы. */
virtual String tryGetAlias() const { return String(); }
/** Установить алиас. */
virtual void setAlias(const String & to)
{
throw Exception("Can't set alias of " + getColumnName(), ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
}
2011-08-09 19:19:00 +00:00
/** Получить текст, который идентифицирует этот элемент. */
2012-12-27 16:23:12 +00:00
virtual String getID() const = 0;
2011-08-09 19:19:00 +00:00
2011-12-12 06:15:34 +00:00
/** Получить глубокую копию дерева. */
virtual ASTPtr clone() const = 0;
2011-12-12 06:15:34 +00:00
/** Get text, describing and identifying this element and its subtree.
* Usually it consist of element's id and getTreeID of all children.
*/
2016-11-20 12:43:20 +00:00
String getTreeID() const;
void getTreeIDImpl(WriteBuffer & out) const;
/** Get hash code, identifying this element and its subtree.
*/
using Hash = std::pair<UInt64, UInt64>;
Hash getTreeHash() const;
void getTreeHashImpl(SipHash & hash_state) const;
void dumpTree(std::ostream & ostr, size_t indent = 0) const
{
String indent_str(indent, '-');
ostr << indent_str << getID() << ", " << this << std::endl;
for (const auto & child : children)
child->dumpTree(ostr, indent + 1);
}
/** Проверить глубину дерева.
* Если задано max_depth и глубина больше - кинуть исключение.
* Возвращает глубину дерева.
*/
size_t checkDepth(size_t max_depth) const
{
return checkDepthImpl(max_depth, 0);
}
2014-07-03 22:39:13 +00:00
/** То же самое для общего количества элементов дерева.
*/
2016-11-20 12:43:20 +00:00
size_t checkSize(size_t max_size) const;
/** Получить set из имен индентификаторов
*/
virtual void collectIdentifierNames(IdentifierNameSet & set) const
{
for (const auto & child : children)
child->collectIdentifierNames(set);
}
/// Преобразовать в строку.
/// Настройки формата.
struct FormatSettings
{
std::ostream & ostr;
bool hilite;
bool one_line;
char nl_or_ws;
FormatSettings(std::ostream & ostr_, bool hilite_, bool one_line_)
: ostr(ostr_), hilite(hilite_), one_line(one_line_)
{
nl_or_ws = one_line ? ' ' : '\n';
}
};
/// Состояние. Например, может запоминаться множество узлов, которых мы уже обошли.
struct FormatState
{
/** Запрос SELECT, в котором найден алиас; идентификатор узла с таким алиасом.
* Нужно, чтобы когда узел встретился повторно, выводить только алиас.
*/
std::set<std::pair<const IAST *, std::string>> printed_asts_with_alias;
};
/// Состояние, которое копируется при форматировании каждого узла. Например, уровень вложенности.
struct FormatStateStacked
{
2015-08-09 05:10:43 +00:00
UInt8 indent = 0;
bool need_parens = false;
const IAST * current_select = nullptr;
};
void format(const FormatSettings & settings) const
{
FormatState state;
formatImpl(settings, state, FormatStateStacked());
}
virtual void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
throw Exception("Unknown element in AST: " + getID()
+ ((range.first && (range.second > range.first))
? " '" + std::string(range.first, range.second - range.first) + "'"
: ""),
ErrorCodes::UNKNOWN_ELEMENT_IN_AST);
}
void writeAlias(const String & name, std::ostream & s, bool hilite) const;
protected:
/// Для подсветки синтаксиса.
static const char * hilite_keyword;
static const char * hilite_identifier;
static const char * hilite_function;
static const char * hilite_operator;
static const char * hilite_alias;
static const char * hilite_none;
private:
2016-11-20 12:43:20 +00:00
size_t checkDepthImpl(size_t max_depth, size_t level) const;
2010-06-24 19:12:10 +00:00
};
/// Квотировать идентификатор обратными кавычками, если это требуется.
String backQuoteIfNeed(const String & x);
2010-06-24 19:12:10 +00:00
}