Revert "dbms: improvement (incomplete) [#METR-16164]."

This reverts commit 6f4f44ce7980cace32edd0913b8d1d53cd51682b.
This commit is contained in:
Alexey Milovidov 2015-05-03 12:13:08 +03:00
parent 3b5fe94b82
commit 310ed66b00
33 changed files with 109 additions and 343 deletions

View File

@ -21,11 +21,6 @@ struct UInt128
bool operator!= (const UInt64 rhs) const { return first != rhs || second != 0; }
UInt128 & operator= (const UInt64 rhs) { first = rhs; second = 0; return *this; }
bool operator< (const UInt128 rhs) const
{
return std::tie(first, second) < std::tie(rhs.first, rhs.second);
}
};
struct UInt128Hash

View File

@ -18,7 +18,6 @@
#include <DB/IO/WriteBufferFromString.h>
#include <DB/IO/DoubleConverter.h>
#include <DB/Common/SipHash.h>
namespace DB
@ -573,64 +572,6 @@ public:
}
};
/** Обновляет состояние хэш-функции значением. */
class FieldVisitorUpdateHash : public StaticVisitor<>
{
private:
SipHash & hash;
public:
FieldVisitorUpdateHash(SipHash & hash_) : hash(hash_) {}
void operator() (const Null & x) const
{
auto type = Field::Types::Null;
hash.update(reinterpret_cast<const char *>(&type), 1);
}
void operator() (const UInt64 & x) const
{
auto type = Field::Types::UInt64;
hash.update(reinterpret_cast<const char *>(&type), 1);
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
}
void operator() (const Int64 & x) const
{
auto type = Field::Types::Int64;
hash.update(reinterpret_cast<const char *>(&type), 1);
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
}
void operator() (const Float64 & x) const
{
auto type = Field::Types::Float64;
hash.update(reinterpret_cast<const char *>(&type), 1);
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
}
void operator() (const String & x) const
{
auto type = Field::Types::String;
hash.update(reinterpret_cast<const char *>(&type), 1);
size_t size = x.size();
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
hash.update(x.data(), x.size());
}
void operator() (const Array & x) const
{
auto type = Field::Types::Array;
hash.update(reinterpret_cast<const char *>(&type), 1);
size_t size = x.size();
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
for (const auto & elem : x)
apply_visitor(*this, elem);
}
};
/** Выводит текстовое представление типа, как литерала в SQL запросе */
class FieldVisitorToString : public StaticVisitor<String>
{

View File

@ -39,11 +39,11 @@ private:
*/
struct OrWithExpression
{
OrWithExpression(ASTFunction * or_function_, UInt128 expression_);
OrWithExpression(ASTFunction * or_function_, const std::string & expression_);
bool operator<(const OrWithExpression & rhs) const;
ASTFunction * or_function;
const UInt128 expression;
const std::string expression;
};
struct Equalities

View File

@ -89,13 +89,6 @@ public:
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return ("AlterQuery_" + database + "_" + table); };
void updateHashWith(SipHash & hash) const override
{
hash.update("AlterQuery", strlen("AlterQuery") + 1);
hash.update(database.data(), database.size() + 1);
hash.update(table.data(), table.size() + 1);
}
ASTPtr clone() const override
{
ASTAlterQuery * res = new ASTAlterQuery(*this);

View File

@ -16,11 +16,6 @@ public:
String getID() const override { return "Asterisk"; }
ASTPtr clone() const override { return new ASTAsterisk(*this); }
String getColumnName() const override { return "*"; }
void updateHashWith(SipHash & hash) const override
{
hash.update("Asterisk", strlen("Asterisk") + 1);
}
};
}

View File

@ -12,13 +12,6 @@ struct ASTCheckQuery : public IAST
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return ("CheckQuery_" + database + "_" + table); };
void updateHashWith(SipHash & hash) const override
{
hash.update("CheckQuery", strlen("CheckQuery") + 1);
hash.update(database.data(), database.size() + 1);
hash.update(table.data(), table.size() + 1);
}
ASTPtr clone() const override
{
return new ASTCheckQuery(*this);

View File

@ -21,12 +21,6 @@ public:
String getID() const override { return "ColumnDeclaration_" + name; }
void updateHashWith(SipHash & hash) const override
{
hash.update("ColumnDeclaration", strlen("ColumnDeclaration") + 1);
hash.update(name.data(), name.size() + 1);
}
ASTPtr clone() const override
{
const auto res = new ASTColumnDeclaration{*this};

View File

@ -30,18 +30,10 @@ public:
ASTCreateQuery() = default;
ASTCreateQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return (attach ? "AttachQuery_" : "CreateQuery_") + database + "_" + table; };
void updateHashWith(SipHash & hash) const override
{
hash.update(reinterpret_cast<const char *>(&attach), sizeof(attach));
hash.update("CreateQuery", strlen("CreateQuery") + 1);
hash.update(database.data(), database.size() + 1);
hash.update(table.data(), table.size() + 1);
}
ASTPtr clone() const override
{
ASTCreateQuery * res = new ASTCreateQuery(*this);

View File

@ -19,18 +19,10 @@ public:
ASTDropQuery() = default;
ASTDropQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return (detach ? "DetachQuery_" : "DropQuery_") + database + "_" + table; };
void updateHashWith(SipHash & hash) const override
{
hash.update(reinterpret_cast<const char *>(&detach), sizeof(detach));
hash.update("DropQuery", strlen("DropQuery") + 1);
hash.update(database.data(), database.size() + 1);
hash.update(table.data(), table.size() + 1);
}
ASTPtr clone() const override { return new ASTDropQuery(*this); }
};

View File

@ -16,21 +16,16 @@ class ASTExpressionList : public IAST
public:
ASTExpressionList() = default;
ASTExpressionList(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "ExpressionList"; }
void updateHashWith(SipHash & hash) const override
{
hash.update("ExpressionList", strlen("ExpressionList") + 1);
}
ASTPtr clone() const override
{
const auto res = new ASTExpressionList(*this);
ASTPtr ptr{res};
res->children.clear();
for (const auto & child : children)
res->children.emplace_back(child->clone());

View File

@ -5,6 +5,7 @@
#include <DB/Functions/IFunction.h>
#include <DB/AggregateFunctions/IAggregateFunction.h>
#include <DB/IO/WriteBufferFromString.h>
#include <DB/Common/SipHash.h>
namespace DB
@ -37,15 +38,40 @@ public:
ASTFunction() = default;
ASTFunction(const StringRange range_) : ASTWithAlias(range_) {}
String getColumnName() const override
{
SipHash hash;
hash.update(name.data(), name.size());
if (parameters)
{
hash.update("(", 1);
for (const auto & param : parameters->children)
{
String param_name = param->getColumnName(); /// TODO Сделать метод updateHashWith.
hash.update(param_name.data(), param_name.size() + 1);
}
hash.update(")", 1);
}
hash.update("(", 1);
for (const auto & arg : arguments->children)
{
String arg_name = arg->getColumnName();
hash.update(arg_name.data(), arg_name.size() + 1);
}
hash.update(")", 1);
UInt64 low, high;
hash.get128(low, high);
return toString(high) + "_" + toString(low); /// TODO hex.
}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Function_" + name; }
void updateHashWith(SipHash & hash) const override
{
hash.update("Function", strlen("Function") + 1);
hash.update(name.data(), name.size() + 1);
}
ASTPtr clone() const override
{
ASTFunction * res = new ASTFunction(*this);

View File

@ -35,12 +35,6 @@ public:
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Identifier_" + name; }
void updateHashWith(SipHash & hash) const override
{
hash.update("Identifier", strlen("Identifier") + 1);
hash.update(name.data(), name.size() + 1);
}
ASTPtr clone() const override { return new ASTIdentifier(*this); }
void collectIdentifierNames(IdentifierNameSet & set) const override

View File

@ -26,17 +26,10 @@ public:
ASTInsertQuery() = default;
ASTInsertQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "InsertQuery_" + database + "_" + table; };
void updateHashWith(SipHash & hash) const override
{
hash.update("InsertQuery", strlen("InsertQuery") + 1);
hash.update(database.data(), database.size() + 1);
hash.update(table.data(), table.size() + 1);
}
ASTPtr clone() const override
{
ASTInsertQuery * res = new ASTInsertQuery(*this);

View File

@ -69,14 +69,6 @@ public:
return res;
};
void updateHashWith(SipHash & hash) const override
{
hash.update("Join", strlen("Join") + 1);
hash.update(reinterpret_cast<const char *>(&locality), sizeof(locality));
hash.update(reinterpret_cast<const char *>(&strictness), sizeof(strictness));
hash.update(reinterpret_cast<const char *>(&kind), sizeof(kind));
}
ASTPtr clone() const override
{
ASTJoin * res = new ASTJoin(*this);

View File

@ -25,12 +25,6 @@ public:
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Literal_" + apply_visitor(FieldVisitorDump(), value); }
void updateHashWith(SipHash & hash) const override
{
hash.update("Literal", strlen("Literal") + 1);
apply_visitor(FieldVisitorUpdateHash(hash), value);
}
ASTPtr clone() const override { return new ASTLiteral(*this); }
};

View File

@ -23,12 +23,6 @@ public:
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "NameTypePair_" + name; }
void updateHashWith(SipHash & hash) const override
{
hash.update("NameTypePair", strlen("NameTypePair") + 1);
hash.update(name.data(), name.size() + 1);
}
ASTPtr clone() const override
{
ASTNameTypePair * res = new ASTNameTypePair(*this);

View File

@ -17,17 +17,10 @@ public:
ASTOptimizeQuery() = default;
ASTOptimizeQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "OptimizeQuery_" + database + "_" + table; };
void updateHashWith(SipHash & hash) const override
{
hash.update("OptimizeQuery", strlen("OptimizeQuery") + 1);
hash.update(database.data(), database.size() + 1);
hash.update(table.data(), table.size() + 1);
}
ASTPtr clone() const override { return new ASTOptimizeQuery(*this); }
};

View File

@ -15,24 +15,19 @@ class ASTOrderByElement : public IAST
{
public:
int direction; /// 1, если ASC, -1, если DESC
/** Collator для locale-specific сортировки строк.
* Если nullptr, то производится сортировка по байтам.
*/
Poco::SharedPtr<Collator> collator;
ASTOrderByElement() = default;
ASTOrderByElement(const StringRange range_, const int direction_, const Poco::SharedPtr<Collator> & collator_ = nullptr)
: IAST(range_), direction(direction_), collator(collator_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "OrderByElement"; }
void updateHashWith(SipHash & hash) const override
{
hash.update("OrderByElement", strlen("OrderByElement") + 1);
}
ASTPtr clone() const override { return new ASTOrderByElement(*this); }
};

View File

@ -5,8 +5,8 @@
namespace DB
{
/** Запрос с секцией FORMAT.
*/
class ASTQueryWithOutput : public IAST
@ -28,11 +28,6 @@ public: \
Name(StringRange range_) : ASTQueryWithOutput(range_) {} \
String getID() const override { return ID; }; \
\
void updateHashWith(SipHash & hash) const override \
{ \
hash.update(ID, strlen(ID) + 1); \
} \
\
ASTPtr clone() const override \
{ \
Name * res = new Name(*this); \

View File

@ -6,8 +6,8 @@
namespace DB
{
/** Запрос с указанием названия таблицы и, возможно, БД и секцией FORMAT.
*/
class ASTQueryWithTableAndOutput : public ASTQueryWithOutput
@ -15,12 +15,12 @@ namespace DB
public:
String database;
String table;
ASTQueryWithTableAndOutput() = default;
ASTQueryWithTableAndOutput(const StringRange range_) : ASTQueryWithOutput(range_) {}
};
/// Объявляет класс-наследник ASTQueryWithTableAndOutput с реализованными методами getID и clone.
#define DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(Name, ID) \
class Name : public ASTQueryWithTableAndOutput \
@ -29,14 +29,7 @@ public: \
Name() = default; \
Name(const StringRange range_) : ASTQueryWithTableAndOutput(range_) {} \
String getID() const override { return ID"_" + database + "_" + table; }; \
\
void updateHashWith(SipHash & hash) const override \
{ \
hash.update(ID, strlen(ID) + 1); \
hash.update(database.data(), database.size() + 1); \
hash.update(table.data(), table.size() + 1); \
} \
\
\
ASTPtr clone() const override \
{ \
Name * res = new Name(*this); \

View File

@ -29,15 +29,10 @@ public:
ASTRenameQuery() = default;
ASTRenameQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Rename"; };
void updateHashWith(SipHash & hash) const override
{
hash.update("Rename", strlen("Rename") + 1);
}
ASTPtr clone() const override { return new ASTRenameQuery(*this); }
};

View File

@ -39,11 +39,6 @@ public:
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "SelectQuery"; };
void updateHashWith(SipHash & hash) const override
{
hash.update("SelectQuery", strlen("SelectQuery") + 1);
}
/// Проверить наличие функции arrayJoin. (Не большого ARRAY JOIN.)
static bool hasArrayJoin(const ASTPtr & ast)
{

View File

@ -22,11 +22,6 @@ public:
String getID() const override { return "Set_" + getColumnName(); }
ASTPtr clone() const override { return new ASTSet(*this); }
String getColumnName() const override { return column_name; }
void updateHashWith(SipHash & hash) const override
{
hash.update("Set", strlen("Set") + 1);
}
};
}

View File

@ -26,14 +26,9 @@ public:
ASTSetQuery() = default;
ASTSetQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "SetQuery"; };
void updateHashWith(SipHash & hash) const override
{
hash.update("SetQuery", strlen("SetQuery") + 1);
}
String getID() const override { return "Set"; };
ASTPtr clone() const override { return new ASTSetQuery(*this); }
};

View File

@ -20,14 +20,9 @@ public:
ASTShowTablesQuery() = default;
ASTShowTablesQuery(const StringRange range_) : ASTQueryWithOutput(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "ShowTablesQuery"; };
void updateHashWith(SipHash & hash) const override
{
hash.update("ShowTablesQuery", strlen("ShowTablesQuery") + 1);
}
String getID() const override { return "ShowTables"; };
ASTPtr clone() const override
{
@ -35,13 +30,13 @@ public:
ASTPtr ptr{res};
res->children.clear();
if (format)
{
res->format = format->clone();
res->children.push_back(res->format);
}
return ptr;
}
};

View File

@ -16,15 +16,10 @@ class ASTSubquery : public IAST
public:
ASTSubquery() = default;
ASTSubquery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Subquery"; }
void updateHashWith(SipHash & hash) const override
{
hash.update("Subquery", strlen("Subquery") + 1);
}
ASTPtr clone() const override
{
const auto res = new ASTSubquery{*this};
@ -38,11 +33,7 @@ public:
return ptr;
}
String getColumnName() const override
{
auto id = getTreeID();
return toString(id.first) + "_" + toString(id.second);
}
String getColumnName() const override { return getTreeID(); }
};
}

View File

@ -16,16 +16,10 @@ public:
ASTUseQuery() = default;
ASTUseQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "UseQuery_" + database; };
void updateHashWith(SipHash & hash) const override
{
hash.update("UseQuery", strlen("UseQuery") + 1);
hash.update(database.data(), database.size() + 1);
}
ASTPtr clone() const override { return new ASTUseQuery(*this); }
};

View File

@ -9,10 +9,8 @@
#include <Yandex/Common.h>
#include <DB/Core/Types.h>
#include <DB/Common/UInt128.h>
#include <DB/Core/Exception.h>
#include <DB/Core/ErrorCodes.h>
#include <DB/Common/SipHash.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/Parsers/StringRange.h>
@ -45,67 +43,15 @@ public:
IAST(const StringRange range_) : range(range_) {}
virtual ~IAST() = default;
/** Получить имя, однозначно идентифицирующее выражение, если элемент является столбцом. У одинаковых выражений будет одинаковое имя. */
virtual String getColumnName() const
{
/// По-умолчанию - подчёркивание, а затем getTreeID в hex-е.
/** Получить каноническое имя столбца, если элемент является столбцом */
virtual String getColumnName() const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::NOT_A_COLUMN); }
union
{
UInt128 id;
UInt8 id_bytes[16];
};
id = getTreeID();
String res(1 + 2 * sizeof(id), '_');
for (size_t i = 0; i < sizeof(id); ++i)
{
res[i * 2 + 1] = (id_bytes[i] / 16) < 10 ? ('0' + (id_bytes[i] / 16)) : ('A' + (id_bytes[i] / 16 - 10));
res[i * 2 + 2] = (id_bytes[i] % 16) < 10 ? ('0' + (id_bytes[i] % 16)) : ('A' + (id_bytes[i] % 16 - 10));
}
return res;
}
/** Получить алиас, если он есть, или имя столбца, если его нет. */
/** Получить алиас, если он есть, или каноническое имя столбца, если его нет. */
virtual String getAliasOrColumnName() const { return getColumnName(); }
/** Получить алиас, если он есть, или пустую строку, если его нет, или если элемент не поддерживает алиасы. */
virtual String tryGetAlias() const { return String(); }
/** Обновить состояние хэш-функции элементом дерева. */
virtual void updateHashWith(SipHash & hash) const = 0;
/** Обновить состояние хэш-функции целым поддеревом. Используется для склейки одинаковых выражений. */
void updateHashWithTree(SipHash & hash) const
{
updateHashWith(hash);
if (!children.empty())
{
size_t size = children.size();
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
for (size_t i = 0; i < size; ++i)
{
hash.update(reinterpret_cast<const char *>(&i), sizeof(i));
children[i]->updateHashWithTree(hash);
}
}
}
/** Получить идентификатор поддерева. Используется для склейки одинаковых выражений.
*/
UInt128 getTreeID() const
{
SipHash hash;
updateHashWithTree(hash);
UInt128 res;
hash.get128(reinterpret_cast<char *>(&res));
return res;
}
/** Установить алиас. */
virtual void setAlias(const String & to)
{
@ -125,6 +71,37 @@ public:
(*it)->is_visited = false;
}
/** Получить текст, который идентифицирует этот элемент и всё поддерево.
* Обычно он содержит идентификатор элемента и getTreeID от всех детей.
*/
String getTreeID() const
{
std::stringstream s;
s << getID();
if (!children.empty())
{
s << "(";
for (ASTs::const_iterator it = children.begin(); it != children.end(); ++it)
{
if (it != children.begin())
s << ", ";
s << (*it)->getTreeID();
}
s << ")";
}
return s.str();
}
void dumpTree(std::ostream & ostr, size_t indent = 0) const
{
String indent_str(indent, '-');
ostr << indent_str << getID() << ", " << this << std::endl;
for (ASTs::const_iterator it = children.begin(); it != children.end(); ++it)
(*it)->dumpTree(ostr, indent + 1);
}
/** Проверить глубину дерева.
* Если задано max_depth и глубина больше - кинуть исключение.
* Возвращает глубину дерева.
@ -139,8 +116,8 @@ public:
size_t checkSize(size_t max_size) const
{
size_t res = 1;
for (const auto & ast : children)
res += ast->checkSize(max_size);
for (ASTs::const_iterator it = children.begin(); it != children.end(); ++it)
res += (*it)->checkSize(max_size);
if (res > max_size)
throw Exception("AST is too big. Maximum: " + toString(max_size), ErrorCodes::TOO_BIG_AST);
@ -149,22 +126,22 @@ public:
}
/** Получить set из имен индентификаторов
*/
*/
virtual void collectIdentifierNames(IdentifierNameSet & set) const
{
for (const auto & ast : children)
ast->collectIdentifierNames(set);
for (ASTs::const_iterator it = children.begin(); it != children.end(); ++it)
(*it)->collectIdentifierNames(set);
}
private:
size_t checkDepthImpl(size_t max_depth, size_t level) const
{
size_t res = level + 1;
for (const auto & ast : children)
for (ASTs::const_iterator it = children.begin(); it != children.end(); ++it)
{
if (level >= max_depth)
throw Exception("AST is too deep. Maximum: " + toString(max_depth), ErrorCodes::TOO_DEEP_AST);
res = std::max(res, ast->checkDepthImpl(max_depth, level + 1));
res = std::max(res, (*it)->checkDepthImpl(max_depth, level + 1));
}
return res;

View File

@ -41,6 +41,7 @@ int main(int argc, char ** argv)
formatAST(*ast, std::cerr);
std::cerr << std::endl;
std::cerr << ast->getTreeID() << std::endl;
Context context;
context.getColumns().push_back(NameAndTypePair("number", new DataTypeUInt64));

View File

@ -106,6 +106,7 @@ int main(int argc, char ** argv)
formatAST(*ast, std::cerr);
std::cerr << std::endl;
std::cerr << ast->getTreeID() << std::endl;
/// создаём объект существующей таблицы хит лога

View File

@ -1653,43 +1653,10 @@ void ExpressionAnalyzer::appendProjectResult(DB::ExpressionActionsChain & chain,
NamesWithAliases result_columns;
ASTs asts = select_query->select_expression_list->children;
/// Выбор имён для столбцов результата.
size_t i = 1;
for (const auto & ast : asts)
for (size_t i = 0; i < asts.size(); ++i)
{
String source_column_name = ast->getColumnName();
String result_column_name = ast->tryGetAlias();
/// Если не задан алиас - нужно сгенерировать какое-нибудь имя автоматически.
if (result_column_name.empty())
{
if (typeid_cast<const ASTLiteral *>(ast.get()) || typeid_cast<const ASTIdentifier *>(ast.get()))
{
/// Если выражение простое, то будем использовать его имя.
result_column_name = source_column_name;
}
else if (auto func = typeid_cast<const ASTFunction *>(ast.get()))
{
/// Для функций используем имя вида _1_func, где func - имя функции.
WriteBufferFromString wb(result_column_name);
writeChar('_', wb);
writeIntText(i, wb);
writeChar('_', wb);
writeString(func->name, wb);
}
else
{
/// Если выражение сложное и для него не задан алиас, будем использовать имя вида _1, _2, ...
WriteBufferFromString wb(result_column_name);
writeChar('_', wb);
writeIntText(i, wb);
}
}
result_columns.emplace_back(source_column_name, result_column_name);
step.required_output.emplace_back(result_columns.back().second);
++i;
result_columns.emplace_back(asts[i]->getColumnName(), asts[i]->getAliasOrColumnName());
step.required_output.push_back(result_columns.back().second);
}
step.actions->add(ExpressionAction::project(result_columns));

View File

@ -12,7 +12,7 @@
namespace DB
{
LogicalExpressionsOptimizer::OrWithExpression::OrWithExpression(ASTFunction * or_function_, UInt128 expression_)
LogicalExpressionsOptimizer::OrWithExpression::OrWithExpression(ASTFunction * or_function_, const std::string & expression_)
: or_function(or_function_), expression(expression_)
{
}

View File

@ -27,6 +27,7 @@ int main(int argc, char ** argv)
std::cout << "Success." << std::endl;
formatAST(*ast, std::cerr);
std::cout << std::endl;
std::cout << std::endl << ast->getTreeID() << std::endl;
return 0;
}