2011-08-09 19:19:00 +00:00
|
|
|
#pragma once
|
2010-06-24 19:12:10 +00:00
|
|
|
|
2013-08-13 08:54:28 +00:00
|
|
|
#include <set>
|
2016-05-28 15:42:22 +00:00
|
|
|
#include <memory>
|
2017-01-17 18:03:32 +00:00
|
|
|
#include <ostream>
|
2010-06-24 19:12:10 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Core/Types.h>
|
|
|
|
#include <Common/Exception.h>
|
|
|
|
#include <Parsers/StringRange.h>
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
2017-01-25 01:53:29 +00:00
|
|
|
class SipHash;
|
|
|
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int NOT_A_COLUMN;
|
|
|
|
extern const int UNKNOWN_TYPE_OF_AST_NODE;
|
|
|
|
extern const int UNKNOWN_ELEMENT_IN_AST;
|
2017-09-17 18:49:43 +00:00
|
|
|
extern const int LOGICAL_ERROR;
|
2016-01-11 21:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using IdentifierNameSet = std::set<String>;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
class IAST;
|
|
|
|
using ASTPtr = std::shared_ptr<IAST>;
|
|
|
|
using ASTs = std::vector<ASTPtr>;
|
|
|
|
|
2017-01-25 01:53:29 +00:00
|
|
|
class WriteBuffer;
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Element of the syntax tree (hereinafter - directed acyclic graph with elements of semantics)
|
2010-06-24 19:12:10 +00:00
|
|
|
*/
|
2017-09-17 18:49:43 +00:00
|
|
|
class IAST : public std::enable_shared_from_this<IAST>
|
2011-08-13 21:05:18 +00:00
|
|
|
{
|
2010-06-24 19:12:10 +00:00
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
ASTs children;
|
|
|
|
StringRange range;
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** A string with a full query.
|
|
|
|
* This pointer does not allow it to be deleted while the range refers to it.
|
2017-04-01 07:20:54 +00:00
|
|
|
*/
|
|
|
|
StringPtr query_string;
|
|
|
|
|
|
|
|
IAST() = default;
|
|
|
|
IAST(const StringRange range_) : range(range_) {}
|
|
|
|
virtual ~IAST() = default;
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Get the canonical name of the column if the element is a column */
|
2017-04-01 07:20:54 +00:00
|
|
|
virtual String getColumnName() const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::NOT_A_COLUMN); }
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Get the alias, if any, or the canonical name of the column, if it is not. */
|
2017-04-01 07:20:54 +00:00
|
|
|
virtual String getAliasOrColumnName() const { return getColumnName(); }
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Get the alias, if any, or an empty string if it does not exist, or if the element does not support aliases. */
|
2017-04-01 07:20:54 +00:00
|
|
|
virtual String tryGetAlias() const { return String(); }
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Set the alias. */
|
2017-04-01 07:20:54 +00:00
|
|
|
virtual void setAlias(const String & to)
|
|
|
|
{
|
|
|
|
throw Exception("Can't set alias of " + getColumnName(), ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Get the text that identifies this element. */
|
2017-04-01 07:20:54 +00:00
|
|
|
virtual String getID() const = 0;
|
|
|
|
|
2017-09-17 18:49:43 +00:00
|
|
|
ASTPtr ptr() { return shared_from_this(); }
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Get a deep copy of the tree. */
|
2017-04-01 07:20:54 +00:00
|
|
|
virtual ASTPtr clone() const = 0;
|
|
|
|
|
|
|
|
/** Get text, describing and identifying this element and its subtree.
|
|
|
|
* Usually it consist of element's id and getTreeID of all children.
|
|
|
|
*/
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Check the depth of the tree.
|
|
|
|
* If max_depth is specified and the depth is greater - throw an exception.
|
|
|
|
* Returns the depth of the tree.
|
2017-04-01 07:20:54 +00:00
|
|
|
*/
|
|
|
|
size_t checkDepth(size_t max_depth) const
|
|
|
|
{
|
|
|
|
return checkDepthImpl(max_depth, 0);
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Same for the total number of tree elements.
|
2017-04-01 07:20:54 +00:00
|
|
|
*/
|
|
|
|
size_t checkSize(size_t max_size) const;
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/** Get `set` from the names of the identifiers
|
2017-04-01 07:20:54 +00:00
|
|
|
*/
|
|
|
|
virtual void collectIdentifierNames(IdentifierNameSet & set) const
|
|
|
|
{
|
|
|
|
for (const auto & child : children)
|
|
|
|
child->collectIdentifierNames(set);
|
|
|
|
}
|
|
|
|
|
2017-09-17 18:49:43 +00:00
|
|
|
template <typename T>
|
|
|
|
void set(T * & field, const ASTPtr & child)
|
|
|
|
{
|
|
|
|
if (!child)
|
|
|
|
return;
|
|
|
|
|
|
|
|
T * casted = dynamic_cast<T *>(child.get());
|
|
|
|
if (!casted)
|
|
|
|
throw Exception("Could not cast AST subtree", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
children.push_back(child);
|
|
|
|
field = casted;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void replace(T * & field, const ASTPtr & child)
|
|
|
|
{
|
|
|
|
if (!child)
|
|
|
|
throw Exception("Trying to replace AST subtree with nullptr", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
T * casted = dynamic_cast<T *>(child.get());
|
|
|
|
if (!casted)
|
|
|
|
throw Exception("Could not cast AST subtree", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
for (ASTPtr & current_child : children)
|
|
|
|
{
|
|
|
|
if (current_child.get() == field)
|
|
|
|
{
|
|
|
|
current_child = child;
|
|
|
|
field = casted;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw Exception("AST subtree not found in children", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/// Convert to a string.
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/// Format settings.
|
2017-04-01 07:20:54 +00:00
|
|
|
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';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/// State. For example, a set of nodes can be remembered, which we already walk through.
|
2017-04-01 07:20:54 +00:00
|
|
|
struct FormatState
|
|
|
|
{
|
2017-05-27 17:29:55 +00:00
|
|
|
/** The SELECT query in which the alias was found; identifier of a node with such an alias.
|
|
|
|
* It is necessary that when the node has met again, output only the alias.
|
2017-04-01 07:20:54 +00:00
|
|
|
*/
|
|
|
|
std::set<std::pair<const IAST *, std::string>> printed_asts_with_alias;
|
|
|
|
};
|
|
|
|
|
2017-05-27 17:29:55 +00:00
|
|
|
/// The state that is copied when each node is formatted. For example, nesting level.
|
2017-04-01 07:20:54 +00:00
|
|
|
struct FormatStateStacked
|
|
|
|
{
|
|
|
|
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;
|
2015-08-05 21:38:31 +00:00
|
|
|
|
2017-04-21 12:39:28 +00:00
|
|
|
public:
|
2017-05-27 17:29:55 +00:00
|
|
|
/// For syntax highlighting.
|
2017-04-01 07:20:54 +00:00
|
|
|
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;
|
2015-08-06 21:32:51 +00:00
|
|
|
|
2014-02-12 12:51:54 +00:00
|
|
|
private:
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t checkDepthImpl(size_t max_depth, size_t level) const;
|
2010-06-24 19:12:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-04-21 12:39:28 +00:00
|
|
|
/// Surrounds an identifier by back quotes if it is necessary.
|
2015-08-05 21:38:31 +00:00
|
|
|
String backQuoteIfNeed(const String & x);
|
|
|
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
}
|