2015-02-18 09:43:36 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2015-02-18 14:55:11 +00:00
|
|
|
|
#include <DB/Parsers/IAST.h>
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <unordered_map>
|
2015-02-18 09:43:36 +00:00
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2016-03-07 04:35:06 +00:00
|
|
|
|
struct Settings;
|
2015-02-18 14:55:11 +00:00
|
|
|
|
class ASTFunction;
|
2015-02-18 09:43:36 +00:00
|
|
|
|
class ASTSelectQuery;
|
|
|
|
|
|
2015-02-18 11:57:44 +00:00
|
|
|
|
/** Этот класс предоставляет функции для оптимизации логических выражений внутри запросов.
|
|
|
|
|
*
|
|
|
|
|
* Для простоты назовём однородной OR-цепочой любое выражение имеющее следующую структуру:
|
|
|
|
|
* expr = x1 OR ... OR expr = xN
|
|
|
|
|
* где expr - произвольное выражение и x1, ..., xN - литералы одного типа
|
|
|
|
|
*/
|
2015-02-18 14:55:11 +00:00
|
|
|
|
class LogicalExpressionsOptimizer final
|
2015-02-18 09:43:36 +00:00
|
|
|
|
{
|
|
|
|
|
public:
|
2015-02-18 14:55:11 +00:00
|
|
|
|
/// Конструктор. Принимает корень DAG запроса.
|
2015-02-18 16:54:42 +00:00
|
|
|
|
LogicalExpressionsOptimizer(ASTSelectQuery * select_query_, const Settings & settings_);
|
2015-02-18 11:57:44 +00:00
|
|
|
|
|
|
|
|
|
/** Заменить все довольно длинные однородные OR-цепочки expr = x1 OR ... OR expr = xN
|
|
|
|
|
* на выражения expr IN (x1, ..., xN).
|
|
|
|
|
*/
|
2015-09-29 14:40:23 +00:00
|
|
|
|
void perform();
|
2015-02-18 09:43:36 +00:00
|
|
|
|
|
|
|
|
|
LogicalExpressionsOptimizer(const LogicalExpressionsOptimizer &) = delete;
|
|
|
|
|
LogicalExpressionsOptimizer & operator=(const LogicalExpressionsOptimizer &) = delete;
|
|
|
|
|
|
|
|
|
|
private:
|
2015-02-20 11:33:21 +00:00
|
|
|
|
/** Функция OR с выражением.
|
|
|
|
|
*/
|
|
|
|
|
struct OrWithExpression
|
|
|
|
|
{
|
2016-03-10 14:24:04 +00:00
|
|
|
|
OrWithExpression(ASTFunction * or_function_, const std::string & expression_,
|
|
|
|
|
const std::string & alias_);
|
2015-02-20 11:33:21 +00:00
|
|
|
|
bool operator<(const OrWithExpression & rhs) const;
|
|
|
|
|
|
|
|
|
|
ASTFunction * or_function;
|
2015-05-03 09:13:08 +00:00
|
|
|
|
const std::string expression;
|
2016-03-10 14:24:04 +00:00
|
|
|
|
const std::string alias;
|
2015-02-20 11:33:21 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-02-19 14:55:47 +00:00
|
|
|
|
struct Equalities
|
|
|
|
|
{
|
|
|
|
|
std::vector<ASTFunction *> functions;
|
|
|
|
|
bool is_processed = false;
|
|
|
|
|
};
|
2015-02-20 11:33:21 +00:00
|
|
|
|
|
2015-02-18 18:18:37 +00:00
|
|
|
|
using DisjunctiveEqualityChainsMap = std::map<OrWithExpression, Equalities>;
|
|
|
|
|
using DisjunctiveEqualityChain = DisjunctiveEqualityChainsMap::value_type;
|
2015-02-18 09:43:36 +00:00
|
|
|
|
|
|
|
|
|
private:
|
2015-02-18 13:53:19 +00:00
|
|
|
|
/** Собрать информация про все равенства входящие в цепочки OR (не обязательно однородные).
|
|
|
|
|
* Эта информация сгруппирована по выражению, которое стоит в левой части равенства.
|
|
|
|
|
*/
|
2015-02-18 09:43:36 +00:00
|
|
|
|
void collectDisjunctiveEqualityChains();
|
2015-02-18 11:57:44 +00:00
|
|
|
|
|
|
|
|
|
/** Проверить, что множество равенств expr = x1, ..., expr = xN выполняет два следующих требования:
|
|
|
|
|
* 1. Оно не слишком маленькое
|
|
|
|
|
* 2. x1, ... xN имеют один и тот же тип
|
|
|
|
|
*/
|
2015-02-18 13:53:19 +00:00
|
|
|
|
bool mayOptimizeDisjunctiveEqualityChain(const DisjunctiveEqualityChain & chain) const;
|
2015-02-18 11:57:44 +00:00
|
|
|
|
|
2015-02-19 14:55:47 +00:00
|
|
|
|
/// Вставить выражение IN в OR-цепочку.
|
|
|
|
|
void addInExpression(const DisjunctiveEqualityChain & chain);
|
|
|
|
|
|
|
|
|
|
/// Удалить равенства, которые были заменены выражениями IN.
|
|
|
|
|
void cleanupOrExpressions();
|
2015-02-18 11:57:44 +00:00
|
|
|
|
|
2015-02-18 18:18:37 +00:00
|
|
|
|
/// Удалить выражения OR, которые имеют только один операнд.
|
2015-02-18 09:43:36 +00:00
|
|
|
|
void fixBrokenOrExpressions();
|
|
|
|
|
|
2016-03-10 14:24:04 +00:00
|
|
|
|
/// Восстановить исходный порядок столбцов после оптимизации.
|
|
|
|
|
void reorderColumns();
|
|
|
|
|
|
2015-02-18 16:54:42 +00:00
|
|
|
|
private:
|
|
|
|
|
using ParentNodes = std::vector<IAST *>;
|
2015-02-18 22:13:54 +00:00
|
|
|
|
using FunctionParentMap = std::unordered_map<IAST *, ParentNodes>;
|
2016-03-10 14:24:04 +00:00
|
|
|
|
using ColumnToPosition = std::unordered_map<IAST *, size_t>;
|
2015-02-18 16:54:42 +00:00
|
|
|
|
|
2015-02-18 09:43:36 +00:00
|
|
|
|
private:
|
|
|
|
|
ASTSelectQuery * select_query;
|
2015-02-18 16:54:42 +00:00
|
|
|
|
const Settings & settings;
|
2015-02-18 11:57:44 +00:00
|
|
|
|
/// Информация про OR-цепочки внутри запроса.
|
2015-02-18 18:18:37 +00:00
|
|
|
|
DisjunctiveEqualityChainsMap disjunctive_equality_chains_map;
|
2015-02-20 10:37:55 +00:00
|
|
|
|
/// Количество обработанных OR-цепочек.
|
|
|
|
|
size_t processed_count = 0;
|
2015-02-18 14:55:11 +00:00
|
|
|
|
/// Родители функций OR.
|
|
|
|
|
FunctionParentMap or_parent_map;
|
2016-03-10 14:24:04 +00:00
|
|
|
|
/// Позиция каждого столбца.
|
|
|
|
|
ColumnToPosition column_to_position;
|
2015-02-18 09:43:36 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-02-18 17:02:51 +00:00
|
|
|
|
}
|