2014-06-12 02:31:30 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
|
#include <Poco/RWLock.h>
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
2016-07-22 20:39:28 +00:00
|
|
|
|
#include <DB/Parsers/ASTTablesInSelectQuery.h>
|
2014-06-18 18:31:35 +00:00
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
#include <DB/Interpreters/AggregationCommon.h>
|
2017-01-21 04:24:28 +00:00
|
|
|
|
#include <DB/Interpreters/SettingsCommon.h>
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Common/Arena.h>
|
|
|
|
|
#include <DB/Common/HashTable/HashMap.h>
|
|
|
|
|
|
2017-03-28 06:51:22 +00:00
|
|
|
|
#include <DB/Columns/ColumnString.h>
|
|
|
|
|
#include <DB/Columns/ColumnFixedString.h>
|
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
#include <DB/DataStreams/IBlockInputStream.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2017-03-28 06:51:22 +00:00
|
|
|
|
/// Helpers to obtain keys (to use in a hash table or similar data structure) for various equi-JOINs.
|
|
|
|
|
|
|
|
|
|
/// UInt8/16/32/64 or another types with same number of bits.
|
|
|
|
|
template <typename FieldType>
|
|
|
|
|
struct JoinKeyGetterOneNumber
|
|
|
|
|
{
|
|
|
|
|
using Key = FieldType;
|
|
|
|
|
|
|
|
|
|
const FieldType * vec;
|
|
|
|
|
|
|
|
|
|
/** Created before processing of each block.
|
|
|
|
|
* Initialize some members, used in another methods, called in inner loops.
|
|
|
|
|
*/
|
|
|
|
|
JoinKeyGetterOneNumber(const ConstColumnPlainPtrs & key_columns)
|
|
|
|
|
{
|
|
|
|
|
vec = &static_cast<const ColumnVector<FieldType> *>(key_columns[0])->getData()[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Key getKey(
|
|
|
|
|
const ConstColumnPlainPtrs & key_columns,
|
|
|
|
|
size_t keys_size, /// number of key columns.
|
|
|
|
|
size_t i, /// row number to get key from.
|
|
|
|
|
const Sizes & key_sizes) const /// If keys are of fixed size - their sizes. Not used for methods with variable-length keys.
|
|
|
|
|
{
|
|
|
|
|
return unionCastToUInt64(vec[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Place additional data into memory pool, if needed, when new key was inserted into hash table.
|
|
|
|
|
static void onNewKey(Key & key, Arena & pool) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// For single String key.
|
|
|
|
|
struct JoinKeyGetterString
|
|
|
|
|
{
|
|
|
|
|
using Key = StringRef;
|
|
|
|
|
|
|
|
|
|
const ColumnString::Offsets_t * offsets;
|
|
|
|
|
const ColumnString::Chars_t * chars;
|
|
|
|
|
|
|
|
|
|
JoinKeyGetterString(const ConstColumnPlainPtrs & key_columns)
|
|
|
|
|
{
|
|
|
|
|
const IColumn & column = *key_columns[0];
|
|
|
|
|
const ColumnString & column_string = static_cast<const ColumnString &>(column);
|
|
|
|
|
offsets = &column_string.getOffsets();
|
|
|
|
|
chars = &column_string.getChars();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Key getKey(
|
|
|
|
|
const ConstColumnPlainPtrs & key_columns,
|
|
|
|
|
size_t keys_size,
|
|
|
|
|
size_t i,
|
|
|
|
|
const Sizes & key_sizes) const
|
|
|
|
|
{
|
|
|
|
|
return StringRef(
|
|
|
|
|
&(*chars)[i == 0 ? 0 : (*offsets)[i - 1]],
|
|
|
|
|
(i == 0 ? (*offsets)[i] : ((*offsets)[i] - (*offsets)[i - 1])) - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void onNewKey(Key & key, Arena & pool)
|
|
|
|
|
{
|
|
|
|
|
key.data = pool.insert(key.data, key.size);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// For single FixedString key.
|
|
|
|
|
struct JoinKeyGetterFixedString
|
|
|
|
|
{
|
|
|
|
|
using Key = StringRef;
|
|
|
|
|
|
|
|
|
|
size_t n;
|
|
|
|
|
const ColumnFixedString::Chars_t * chars;
|
|
|
|
|
|
|
|
|
|
JoinKeyGetterFixedString(const ConstColumnPlainPtrs & key_columns)
|
|
|
|
|
{
|
|
|
|
|
const IColumn & column = *key_columns[0];
|
|
|
|
|
const ColumnFixedString & column_string = static_cast<const ColumnFixedString &>(column);
|
|
|
|
|
n = column_string.getN();
|
|
|
|
|
chars = &column_string.getChars();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Key getKey(
|
|
|
|
|
const ConstColumnPlainPtrs & key_columns,
|
|
|
|
|
size_t keys_size,
|
|
|
|
|
size_t i,
|
|
|
|
|
const Sizes & key_sizes) const
|
|
|
|
|
{
|
|
|
|
|
return StringRef(&(*chars)[i * n], n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void onNewKey(Key & key, Arena & pool)
|
|
|
|
|
{
|
|
|
|
|
key.data = pool.insert(key.data, key.size);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// For keys of fixed size, that could be packed in sizeof TKey width.
|
|
|
|
|
template <typename TKey>
|
|
|
|
|
struct JoinKeyGetterFixed
|
|
|
|
|
{
|
|
|
|
|
using Key = TKey;
|
|
|
|
|
|
|
|
|
|
JoinKeyGetterFixed(const ConstColumnPlainPtrs & key_columns)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Key getKey(
|
|
|
|
|
const ConstColumnPlainPtrs & key_columns,
|
|
|
|
|
size_t keys_size,
|
|
|
|
|
size_t i,
|
|
|
|
|
const Sizes & key_sizes) const
|
|
|
|
|
{
|
|
|
|
|
return packFixed<Key>(i, keys_size, key_columns, key_sizes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void onNewKey(Key & key, Arena & pool) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// Generic method, use crypto hash function.
|
|
|
|
|
struct JoinKeyGetterHashed
|
|
|
|
|
{
|
|
|
|
|
using Key = UInt128;
|
|
|
|
|
|
|
|
|
|
JoinKeyGetterHashed(const ConstColumnPlainPtrs & key_columns)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Key getKey(
|
|
|
|
|
const ConstColumnPlainPtrs & key_columns,
|
|
|
|
|
size_t keys_size,
|
|
|
|
|
size_t i,
|
|
|
|
|
const Sizes & key_sizes) const
|
|
|
|
|
{
|
|
|
|
|
return hash128(i, keys_size, key_columns);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void onNewKey(Key & key, Arena & pool) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
|
struct Limits;
|
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
|
|
|
|
/** Структура данных для реализации JOIN-а.
|
|
|
|
|
* По сути, хэш-таблица: ключи -> строки присоединяемой таблицы.
|
2015-07-23 20:23:24 +00:00
|
|
|
|
* Исключение - CROSS JOIN, где вместо хэш-таблицы просто набор блоков без ключей.
|
2014-06-19 19:00:58 +00:00
|
|
|
|
*
|
2015-07-23 20:23:24 +00:00
|
|
|
|
* JOIN-ы бывают девяти типов: ANY/ALL × LEFT/INNER/RIGHT/FULL, а также CROSS.
|
2014-06-19 19:00:58 +00:00
|
|
|
|
*
|
|
|
|
|
* Если указано ANY - выбрать из "правой" таблицы только одну, первую попавшуюся строку, даже если там более одной соответствующей строки.
|
|
|
|
|
* Если указано ALL - обычный вариант JOIN-а, при котором строки могут размножаться по числу соответствующих строк "правой" таблицы.
|
|
|
|
|
* Вариант ANY работает более оптимально.
|
|
|
|
|
*
|
|
|
|
|
* Если указано INNER - оставить только строки, для которых есть хотя бы одна строка "правой" таблицы.
|
|
|
|
|
* Если указано LEFT - в случае, если в "правой" таблице нет соответствующей строки, заполнить её значениями "по-умолчанию".
|
2015-04-17 08:46:06 +00:00
|
|
|
|
* Если указано RIGHT - выполнить так же, как INNER, запоминая те строки из правой таблицы, которые были присоединены,
|
|
|
|
|
* в конце добавить строки из правой таблицы, которые не были присоединены, подставив в качестве значений для левой таблицы, значения "по-умолчанию".
|
|
|
|
|
* Если указано FULL - выполнить так же, как LEFT, запоминая те строки из правой таблицы, которые были присоединены,
|
|
|
|
|
* в конце добавить строки из правой таблицы, которые не были присоединены, подставив в качестве значений для левой таблицы, значения "по-умолчанию".
|
|
|
|
|
*
|
|
|
|
|
* То есть, LEFT и RIGHT JOIN-ы не являются симметричными с точки зрения реализации.
|
2014-06-19 19:00:58 +00:00
|
|
|
|
*
|
|
|
|
|
* Все соединения делаются по равенству кортежа столбцов "ключей" (эквисоединение).
|
|
|
|
|
* Неравенства и прочие условия не поддерживаются.
|
|
|
|
|
*
|
|
|
|
|
* Реализация такая:
|
|
|
|
|
*
|
|
|
|
|
* 1. "Правая" таблица засовывается в хэш-таблицу в оперативке.
|
|
|
|
|
* Она имеет вид keys -> row в случае ANY или keys -> [rows...] в случае ALL.
|
|
|
|
|
* Это делается в функции insertFromBlock.
|
|
|
|
|
*
|
|
|
|
|
* 2. При обработке "левой" таблицы, присоединяем к ней данные из сформированной хэш-таблицы.
|
|
|
|
|
* Это делается в функции joinBlock.
|
|
|
|
|
*
|
|
|
|
|
* В случае ANY LEFT JOIN - формируем новые столбцы с найденной строкой или значениями по-умолчанию.
|
|
|
|
|
* Самый простой вариант. Количество строк при JOIN-е не меняется.
|
|
|
|
|
*
|
|
|
|
|
* В случае ANY INNER JOIN - формируем новые столбцы с найденной строкой;
|
|
|
|
|
* а также заполняем фильтр - для каких строк значения не нашлось.
|
|
|
|
|
* После чего, фильтруем столбцы "левой" таблицы.
|
|
|
|
|
*
|
|
|
|
|
* В случае ALL ... JOIN - формируем новые столбцы со всеми найденными строками;
|
|
|
|
|
* а также заполняем массив offsets, описывающий, во сколько раз надо размножить строки "левой" таблицы.
|
|
|
|
|
* После чего, размножаем столбцы "левой" таблицы.
|
2014-06-12 02:31:30 +00:00
|
|
|
|
*/
|
|
|
|
|
class Join
|
|
|
|
|
{
|
|
|
|
|
public:
|
2014-07-02 20:23:48 +00:00
|
|
|
|
Join(const Names & key_names_left_, const Names & key_names_right_,
|
2017-01-21 04:24:28 +00:00
|
|
|
|
const Limits & limits, ASTTableJoin::Kind kind_, ASTTableJoin::Strictness strictness_);
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
2015-03-02 01:10:58 +00:00
|
|
|
|
bool empty() { return type == Type::EMPTY; }
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
2015-05-26 00:37:48 +00:00
|
|
|
|
/** Передать информацию о структуре блока.
|
|
|
|
|
* Следует обязательно вызвать до вызовов insertFromBlock.
|
|
|
|
|
*/
|
|
|
|
|
void setSampleBlock(const Block & block);
|
|
|
|
|
|
2014-06-12 04:04:47 +00:00
|
|
|
|
/** Добавить в отображение для соединения блок "правой" таблицы.
|
|
|
|
|
* Возвращает false, если превышено какое-нибудь ограничение, и больше не нужно вставлять.
|
|
|
|
|
*/
|
|
|
|
|
bool insertFromBlock(const Block & block);
|
|
|
|
|
|
|
|
|
|
/** Присоединить к блоку "левой" таблицы новые столбцы из сформированного отображения.
|
|
|
|
|
*/
|
2015-01-29 03:07:58 +00:00
|
|
|
|
void joinBlock(Block & block) const;
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
2015-04-16 09:55:24 +00:00
|
|
|
|
/** Запомнить тотальные значения для последующего использования.
|
|
|
|
|
*/
|
|
|
|
|
void setTotals(const Block & block) { totals = block; }
|
|
|
|
|
bool hasTotals() const { return totals; };
|
|
|
|
|
|
|
|
|
|
void joinTotals(Block & block) const;
|
|
|
|
|
|
2015-04-17 08:46:06 +00:00
|
|
|
|
/** Для RIGHT и FULL JOIN-ов.
|
|
|
|
|
* Поток, в котором значения по-умолчанию из левой таблицы соединены с неприсоединёнными ранее строками из правой таблицы.
|
|
|
|
|
* Использовать только после того, как были сделаны все вызовы joinBlock.
|
|
|
|
|
*/
|
|
|
|
|
BlockInputStreamPtr createStreamWithNonJoinedRows(Block & left_sample_block, size_t max_block_size) const;
|
|
|
|
|
|
2015-01-27 00:52:03 +00:00
|
|
|
|
/// Считает суммарное число ключей во всех Join'ах
|
|
|
|
|
size_t getTotalRowCount() const;
|
|
|
|
|
/// Считает суммарный размер в байтах буфферов всех Join'ов + размер string_pool'а
|
|
|
|
|
size_t getTotalByteCount() const;
|
2014-06-18 18:31:35 +00:00
|
|
|
|
|
2016-07-22 20:39:28 +00:00
|
|
|
|
ASTTableJoin::Kind getKind() const { return kind; }
|
2015-04-18 22:33:24 +00:00
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
|
|
|
|
/// Ссылка на строку в блоке.
|
|
|
|
|
struct RowRef
|
|
|
|
|
{
|
|
|
|
|
const Block * block;
|
|
|
|
|
size_t row_num;
|
|
|
|
|
|
|
|
|
|
RowRef() {}
|
|
|
|
|
RowRef(const Block * block_, size_t row_num_) : block(block_), row_num(row_num_) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// Односвязный список ссылок на строки.
|
|
|
|
|
struct RowRefList : RowRef
|
|
|
|
|
{
|
|
|
|
|
RowRefList * next = nullptr;
|
|
|
|
|
|
|
|
|
|
RowRefList() {}
|
|
|
|
|
RowRefList(const Block * block_, size_t row_num_) : RowRef(block_, row_num_) {}
|
|
|
|
|
};
|
|
|
|
|
|
2015-04-17 08:46:06 +00:00
|
|
|
|
|
|
|
|
|
/** Добавляет или не добавляет флаг - был ли элемент использован.
|
|
|
|
|
* Для реализации RIGHT и FULL JOIN-ов.
|
|
|
|
|
* NOTE: Можно сохранять флаг в один из бит указателя block или номера row_num.
|
|
|
|
|
*/
|
|
|
|
|
template <bool enable, typename Base>
|
|
|
|
|
struct WithUsedFlag;
|
|
|
|
|
|
|
|
|
|
template <typename Base>
|
|
|
|
|
struct WithUsedFlag<true, Base> : Base
|
|
|
|
|
{
|
|
|
|
|
mutable bool used = false;
|
|
|
|
|
using Base::Base;
|
|
|
|
|
using Base_t = Base;
|
|
|
|
|
void setUsed() const { used = true; } /// Может выполняться из разных потоков.
|
|
|
|
|
bool getUsed() const { return used; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename Base>
|
|
|
|
|
struct WithUsedFlag<false, Base> : Base
|
|
|
|
|
{
|
|
|
|
|
using Base::Base;
|
|
|
|
|
using Base_t = Base;
|
|
|
|
|
void setUsed() const {}
|
|
|
|
|
bool getUsed() const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2017-03-28 06:51:22 +00:00
|
|
|
|
#define APPLY_FOR_JOIN_VARIANTS(M) \
|
|
|
|
|
M(key8) \
|
|
|
|
|
M(key16) \
|
|
|
|
|
M(key32) \
|
|
|
|
|
M(key64) \
|
|
|
|
|
M(key_string) \
|
|
|
|
|
M(key_fixed_string) \
|
|
|
|
|
M(keys128) \
|
|
|
|
|
M(keys256) \
|
|
|
|
|
M(hashed)
|
|
|
|
|
|
|
|
|
|
enum class Type
|
|
|
|
|
{
|
|
|
|
|
EMPTY,
|
|
|
|
|
CROSS,
|
|
|
|
|
#define M(NAME) NAME,
|
|
|
|
|
APPLY_FOR_JOIN_VARIANTS(M)
|
|
|
|
|
#undef M
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2014-06-18 19:14:29 +00:00
|
|
|
|
/** Разные структуры данных, которые могут использоваться для соединения.
|
|
|
|
|
*/
|
2015-04-17 08:46:06 +00:00
|
|
|
|
template <typename Mapped>
|
|
|
|
|
struct MapsTemplate
|
2014-06-18 20:08:31 +00:00
|
|
|
|
{
|
2017-03-28 06:51:22 +00:00
|
|
|
|
std::unique_ptr<HashMap<UInt8, Mapped, TrivialHash, HashTableFixedGrower<8>>> key8;
|
|
|
|
|
std::unique_ptr<HashMap<UInt16, Mapped, TrivialHash, HashTableFixedGrower<16>>> key16;
|
|
|
|
|
std::unique_ptr<HashMap<UInt32, Mapped, HashCRC32<UInt32>>> key32;
|
|
|
|
|
std::unique_ptr<HashMap<UInt64, Mapped, HashCRC32<UInt64>>> key64;
|
|
|
|
|
std::unique_ptr<HashMapWithSavedHash<StringRef, Mapped>> key_string;
|
|
|
|
|
std::unique_ptr<HashMapWithSavedHash<StringRef, Mapped>> key_fixed_string;
|
|
|
|
|
std::unique_ptr<HashMap<UInt128, Mapped, UInt128HashCRC32>> keys128;
|
|
|
|
|
std::unique_ptr<HashMap<UInt256, Mapped, UInt256HashCRC32>> keys256;
|
|
|
|
|
std::unique_ptr<HashMap<UInt128, Mapped, UInt128TrivialHash>> hashed;
|
2014-06-18 20:08:31 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-04-17 08:46:06 +00:00
|
|
|
|
using MapsAny = MapsTemplate<WithUsedFlag<false, RowRef>>;
|
|
|
|
|
using MapsAll = MapsTemplate<WithUsedFlag<false, RowRefList>>;
|
|
|
|
|
using MapsAnyFull = MapsTemplate<WithUsedFlag<true, RowRef>>;
|
|
|
|
|
using MapsAllFull = MapsTemplate<WithUsedFlag<true, RowRefList>>;
|
2014-06-18 20:08:31 +00:00
|
|
|
|
|
2014-06-18 19:14:29 +00:00
|
|
|
|
private:
|
2015-04-17 08:46:06 +00:00
|
|
|
|
friend class NonJoinedBlockInputStream;
|
|
|
|
|
|
2016-07-22 20:39:28 +00:00
|
|
|
|
ASTTableJoin::Kind kind;
|
|
|
|
|
ASTTableJoin::Strictness strictness;
|
2014-06-18 19:14:29 +00:00
|
|
|
|
|
2015-01-29 03:07:58 +00:00
|
|
|
|
/// Имена ключевых столбцов (по которым производится соединение) в "левой" таблице.
|
2014-07-02 20:23:48 +00:00
|
|
|
|
const Names key_names_left;
|
2015-01-29 03:07:58 +00:00
|
|
|
|
/// Имена ключевых столбцов (по которым производится соединение) в "правой" таблице.
|
2014-07-02 20:23:48 +00:00
|
|
|
|
const Names key_names_right;
|
2014-06-18 19:14:29 +00:00
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
/** Блоки данных таблицы, с которой идёт соединение.
|
|
|
|
|
*/
|
2014-12-19 02:30:13 +00:00
|
|
|
|
BlocksList blocks;
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
2015-04-17 08:46:06 +00:00
|
|
|
|
MapsAny maps_any; /// Для ANY LEFT|INNER JOIN
|
|
|
|
|
MapsAll maps_all; /// Для ALL LEFT|INNER JOIN
|
|
|
|
|
MapsAnyFull maps_any_full; /// Для ANY RIGHT|FULL JOIN
|
|
|
|
|
MapsAllFull maps_all_full; /// Для ALL RIGHT|FULL JOIN
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
|
|
|
|
/// Дополнительные данные - строки, а также продолжения односвязных списков строк.
|
|
|
|
|
Arena pool;
|
|
|
|
|
|
2016-03-07 05:05:42 +00:00
|
|
|
|
private:
|
2015-03-02 01:10:58 +00:00
|
|
|
|
Type type = Type::EMPTY;
|
|
|
|
|
|
2017-03-28 06:51:22 +00:00
|
|
|
|
static Type chooseMethod(const ConstColumnPlainPtrs & key_columns, Sizes & key_sizes);
|
2014-07-06 19:48:39 +00:00
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
bool keys_fit_128_bits;
|
|
|
|
|
Sizes key_sizes;
|
|
|
|
|
|
2015-06-09 23:50:22 +00:00
|
|
|
|
Block sample_block_with_columns_to_add;
|
|
|
|
|
Block sample_block_with_keys;
|
2015-05-26 00:37:48 +00:00
|
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
|
Poco::Logger * log;
|
2014-07-06 19:48:39 +00:00
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
/// Ограничения на максимальный размер множества
|
|
|
|
|
size_t max_rows;
|
|
|
|
|
size_t max_bytes;
|
|
|
|
|
OverflowMode overflow_mode;
|
|
|
|
|
|
2015-04-16 09:55:24 +00:00
|
|
|
|
Block totals;
|
|
|
|
|
|
2015-01-27 21:24:24 +00:00
|
|
|
|
/** Защищает работу с состоянием в функциях insertFromBlock и joinBlock.
|
|
|
|
|
* Эти функции могут вызываться одновременно из разных потоков только при использовании StorageJoin,
|
|
|
|
|
* и StorageJoin вызывает только эти две функции.
|
|
|
|
|
* Поэтому остальные функции не защинены.
|
|
|
|
|
*/
|
|
|
|
|
mutable Poco::RWLock rwlock;
|
|
|
|
|
|
2015-03-02 01:10:58 +00:00
|
|
|
|
void init(Type type_);
|
2014-06-18 20:08:31 +00:00
|
|
|
|
|
2016-07-22 20:39:28 +00:00
|
|
|
|
template <ASTTableJoin::Strictness STRICTNESS, typename Maps>
|
2014-06-18 20:08:31 +00:00
|
|
|
|
void insertFromBlockImpl(Maps & maps, size_t rows, const ConstColumnPlainPtrs & key_columns, size_t keys_size, Block * stored_block);
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
2017-03-28 06:51:22 +00:00
|
|
|
|
template <ASTTableJoin::Strictness STRICTNESS, typename KeyGetter, typename Map>
|
|
|
|
|
void insertFromBlockImplType(Map & map, size_t rows, const ConstColumnPlainPtrs & key_columns, size_t keys_size, Block * stored_block);
|
|
|
|
|
|
2016-07-22 20:39:28 +00:00
|
|
|
|
template <ASTTableJoin::Kind KIND, ASTTableJoin::Strictness STRICTNESS, typename Maps>
|
2015-01-29 03:11:56 +00:00
|
|
|
|
void joinBlockImpl(Block & block, const Maps & maps) const;
|
2014-06-18 18:31:35 +00:00
|
|
|
|
|
2017-03-28 06:51:22 +00:00
|
|
|
|
template <ASTTableJoin::Kind KIND, ASTTableJoin::Strictness STRICTNESS, typename KeyGetter, typename Map>
|
|
|
|
|
void joinBlockImplType(
|
|
|
|
|
Block & block, const Map & map, size_t rows, const ConstColumnPlainPtrs & key_columns, size_t keys_size,
|
|
|
|
|
size_t num_columns_to_add, size_t num_columns_to_skip, ColumnPlainPtrs & added_columns,
|
|
|
|
|
std::unique_ptr<IColumn::Filter> & filter,
|
|
|
|
|
IColumn::Offset_t & current_offset, std::unique_ptr<IColumn::Offsets_t> & offsets_to_replicate) const;
|
|
|
|
|
|
2015-07-23 20:23:24 +00:00
|
|
|
|
void joinBlockImplCross(Block & block) const;
|
|
|
|
|
|
2014-06-12 02:31:30 +00:00
|
|
|
|
/// Проверить не превышены ли допустимые размеры множества
|
|
|
|
|
bool checkSizeLimits() const;
|
2015-06-09 21:34:45 +00:00
|
|
|
|
|
|
|
|
|
/// Кинуть исключение, если в блоках не совпадают типы ключей.
|
|
|
|
|
void checkTypesOfKeys(const Block & block_left, const Block & block_right) const;
|
2014-06-12 02:31:30 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-05-28 10:35:44 +00:00
|
|
|
|
using JoinPtr = std::shared_ptr<Join>;
|
|
|
|
|
using Joins = std::vector<JoinPtr>;
|
2014-06-12 02:31:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|