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
|
|
|
|
|
{
|
|
|
|
|
|
2015-02-18 14:55:11 +00:00
|
|
|
|
class ASTFunction;
|
2015-02-18 09:43:36 +00:00
|
|
|
|
class ASTSelectQuery;
|
|
|
|
|
|
2015-02-18 14:55:11 +00:00
|
|
|
|
/** Функция OR с выражением.
|
|
|
|
|
*/
|
|
|
|
|
struct OrWithExpression
|
2015-02-18 09:43:36 +00:00
|
|
|
|
{
|
2015-02-18 14:55:11 +00:00
|
|
|
|
OrWithExpression(ASTFunction * or_function_, const std::string & expression_);
|
2015-02-18 09:43:36 +00:00
|
|
|
|
ASTFunction * or_function;
|
|
|
|
|
const std::string expression;
|
|
|
|
|
};
|
|
|
|
|
|
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 15:11:47 +00:00
|
|
|
|
LogicalExpressionsOptimizer(ASTSelectQuery * select_query_);
|
2015-02-18 11:57:44 +00:00
|
|
|
|
|
|
|
|
|
/** Заменить все довольно длинные однородные OR-цепочки expr = x1 OR ... OR expr = xN
|
|
|
|
|
* на выражения expr IN (x1, ..., xN).
|
|
|
|
|
*/
|
2015-02-18 09:43:36 +00:00
|
|
|
|
void optimizeDisjunctiveEqualityChains();
|
|
|
|
|
|
|
|
|
|
LogicalExpressionsOptimizer(const LogicalExpressionsOptimizer &) = delete;
|
|
|
|
|
LogicalExpressionsOptimizer & operator=(const LogicalExpressionsOptimizer &) = delete;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
using Equalities = std::vector<ASTFunction *>;
|
2015-02-18 14:55:11 +00:00
|
|
|
|
using DisjunctiveEqualitiesMap = std::map<OrWithExpression, Equalities>;
|
2015-02-18 11:57:44 +00:00
|
|
|
|
using DisjunctiveEqualityChain = DisjunctiveEqualitiesMap::value_type;
|
2015-02-18 09:43:36 +00:00
|
|
|
|
|
2015-02-18 13:53:19 +00:00
|
|
|
|
using ParentNodes = std::vector<IAST *>;
|
2015-02-18 14:55:11 +00:00
|
|
|
|
using FunctionParentMap = std::unordered_map<ASTFunction *, ParentNodes>;
|
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-18 14:55:11 +00:00
|
|
|
|
/// Заменить однородную OR-цепочку на выражение IN.
|
|
|
|
|
void replaceOrByIn(const DisjunctiveEqualityChain & chain);
|
2015-02-18 11:57:44 +00:00
|
|
|
|
|
2015-02-18 14:55:11 +00:00
|
|
|
|
/// Удалить выражения OR, которые имеют только один операнд.
|
2015-02-18 09:43:36 +00:00
|
|
|
|
void fixBrokenOrExpressions();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
ASTSelectQuery * select_query;
|
2015-02-18 11:57:44 +00:00
|
|
|
|
/// Информация про OR-цепочки внутри запроса.
|
2015-02-18 09:43:36 +00:00
|
|
|
|
DisjunctiveEqualitiesMap disjunctive_equalities_map;
|
2015-02-18 14:55:11 +00:00
|
|
|
|
/// Родители функций OR.
|
|
|
|
|
FunctionParentMap or_parent_map;
|
2015-02-18 09:43:36 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|