2014-06-12 00:48:56 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <DB/Parsers/IAST.h>
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** [GLOBAL] ANY|ALL INNER|LEFT JOIN (subquery) USING (tuple)
|
|
|
|
|
* Замечание: ARRAY JOIN к этому не относится.
|
|
|
|
|
*/
|
|
|
|
|
class ASTJoin : public IAST
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
/// Алгоритм работы при распределённой обработке запроса.
|
|
|
|
|
enum Locality
|
|
|
|
|
{
|
|
|
|
|
Local, /// Выполнить JOIN, используя соответствующие данные в пределах каждого удалённого сервера.
|
|
|
|
|
Global /// Собрать соединяемые данные со всех удалённых серверов, объединить их, затем отправить на каждый удалённый сервер.
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// Оптимизация JOIN-а для большинства простых случаев.
|
|
|
|
|
enum Strictness
|
|
|
|
|
{
|
|
|
|
|
Any, /// Если в "правой" таблице несколько подходящих строк - выбрать из них одну, любую.
|
|
|
|
|
All /// Если в "правой" таблице несколько подходящих строк - размножить строки по ним (обычная семантика JOIN-а).
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// Способ соединения.
|
|
|
|
|
enum Kind
|
|
|
|
|
{
|
|
|
|
|
Inner, /// Оставить только записи, для которых в "правой" таблице есть соответствующая.
|
2015-04-17 08:46:06 +00:00
|
|
|
|
Left, /// Если в "правой" таблице нет соответствующих записей, заполнить столбцы значениями "по-умолчанию".
|
|
|
|
|
Right,
|
2015-07-23 20:23:24 +00:00
|
|
|
|
Full,
|
|
|
|
|
Cross /// Прямое произведение. strictness и using_expr_list не используются.
|
2014-06-12 00:48:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Locality locality = Local;
|
|
|
|
|
Strictness strictness = Any;
|
|
|
|
|
Kind kind = Inner;
|
|
|
|
|
|
2014-07-03 20:32:42 +00:00
|
|
|
|
ASTPtr table; /// "Правая" таблица для соединения - подзапрос или имя таблицы.
|
2014-06-12 00:48:56 +00:00
|
|
|
|
ASTPtr using_expr_list; /// По каким столбцам выполнять соединение.
|
2015-11-08 02:42:33 +00:00
|
|
|
|
ASTPtr on_expr; /// Условие соединения. Поддерживается либо USING либо ON, но не одновременно.
|
2014-06-12 00:48:56 +00:00
|
|
|
|
|
2014-12-17 15:26:24 +00:00
|
|
|
|
ASTJoin() = default;
|
|
|
|
|
ASTJoin(const StringRange range_) : IAST(range_) {}
|
2014-06-12 23:21:38 +00:00
|
|
|
|
|
2014-06-12 00:48:56 +00:00
|
|
|
|
/** Получить текст, который идентифицирует этот элемент. */
|
2014-12-17 15:26:24 +00:00
|
|
|
|
String getID() const override
|
2014-06-12 23:21:38 +00:00
|
|
|
|
{
|
|
|
|
|
String res;
|
|
|
|
|
{
|
|
|
|
|
WriteBufferFromString wb(res);
|
|
|
|
|
|
|
|
|
|
if (locality == Global)
|
|
|
|
|
writeString("Global", wb);
|
|
|
|
|
|
|
|
|
|
writeString(strictness == Any ? "Any" : "All", wb);
|
2015-04-17 08:46:06 +00:00
|
|
|
|
|
|
|
|
|
writeString(
|
|
|
|
|
kind == Inner ? "Inner"
|
|
|
|
|
: (kind == Left ? "Left"
|
|
|
|
|
: (kind == Right ? "Right"
|
2015-07-23 20:23:24 +00:00
|
|
|
|
: (kind == Full ? "Full"
|
|
|
|
|
: "Cross"))), wb);
|
2015-04-17 08:46:06 +00:00
|
|
|
|
|
2014-06-12 23:21:38 +00:00
|
|
|
|
writeString("Join", wb);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-17 15:26:24 +00:00
|
|
|
|
return res;
|
2014-06-12 23:21:38 +00:00
|
|
|
|
};
|
2014-06-12 00:48:56 +00:00
|
|
|
|
|
2014-12-17 15:26:24 +00:00
|
|
|
|
ASTPtr clone() const override
|
2014-06-12 00:48:56 +00:00
|
|
|
|
{
|
|
|
|
|
ASTJoin * res = new ASTJoin(*this);
|
2014-12-17 15:26:24 +00:00
|
|
|
|
ASTPtr ptr{res};
|
|
|
|
|
|
2014-06-12 00:48:56 +00:00
|
|
|
|
res->children.clear();
|
|
|
|
|
|
2014-07-03 20:32:42 +00:00
|
|
|
|
if (table) { res->table = table->clone(); res->children.push_back(res->table); }
|
2014-06-12 00:48:56 +00:00
|
|
|
|
if (using_expr_list) { res->using_expr_list = using_expr_list->clone(); res->children.push_back(res->using_expr_list); }
|
|
|
|
|
|
2014-12-17 15:26:24 +00:00
|
|
|
|
return ptr;
|
2014-06-12 00:48:56 +00:00
|
|
|
|
}
|
2015-08-05 21:38:31 +00:00
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
|
|
|
|
|
{
|
|
|
|
|
frame.need_parens = false;
|
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "");
|
|
|
|
|
|
|
|
|
|
if (locality == ASTJoin::Global)
|
|
|
|
|
settings.ostr << "GLOBAL ";
|
|
|
|
|
|
|
|
|
|
if (kind != ASTJoin::Cross)
|
|
|
|
|
settings.ostr << (strictness == ASTJoin::Any ? "ANY " : "ALL ");
|
|
|
|
|
|
|
|
|
|
settings.ostr << (kind == ASTJoin::Inner ? "INNER "
|
2015-08-14 21:30:48 +00:00
|
|
|
|
: (kind == ASTJoin::Left ? "LEFT "
|
|
|
|
|
: (kind == ASTJoin::Right ? "RIGHT "
|
|
|
|
|
: (kind == ASTJoin::Cross ? "CROSS "
|
|
|
|
|
: "FULL OUTER "))));
|
2015-08-05 21:38:31 +00:00
|
|
|
|
|
|
|
|
|
settings.ostr << "JOIN "
|
2015-08-14 21:30:48 +00:00
|
|
|
|
<< (settings.hilite ? hilite_none : "");
|
2015-08-05 21:38:31 +00:00
|
|
|
|
|
2015-08-14 21:30:48 +00:00
|
|
|
|
table->formatImpl(settings, state, frame);
|
2015-08-05 21:38:31 +00:00
|
|
|
|
|
2015-11-08 02:42:33 +00:00
|
|
|
|
if (using_expr_list)
|
2015-08-05 21:38:31 +00:00
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << " USING " << (settings.hilite ? hilite_none : "");
|
|
|
|
|
using_expr_list->formatImpl(settings, state, frame);
|
|
|
|
|
}
|
2015-11-08 02:42:33 +00:00
|
|
|
|
else if (on_expr)
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << " ON " << (settings.hilite ? hilite_none : "");
|
|
|
|
|
on_expr->formatImpl(settings, state, frame);
|
|
|
|
|
}
|
2015-08-05 21:38:31 +00:00
|
|
|
|
}
|
2014-06-12 00:48:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|