ClickHouse/dbms/include/DB/Interpreters/LogicalExpressionsOptimizer.h
2015-02-20 14:33:21 +03:00

96 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <DB/Parsers/IAST.h>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
namespace DB
{
class Settings;
class ASTFunction;
class ASTSelectQuery;
/** Этот класс предоставляет функции для оптимизации логических выражений внутри запросов.
*
* Для простоты назовём однородной OR-цепочой любое выражение имеющее следующую структуру:
* expr = x1 OR ... OR expr = xN
* где expr - произвольное выражение и x1, ..., xN - литералы одного типа
*/
class LogicalExpressionsOptimizer final
{
public:
/// Конструктор. Принимает корень DAG запроса.
LogicalExpressionsOptimizer(ASTSelectQuery * select_query_, const Settings & settings_);
/** Заменить все довольно длинные однородные OR-цепочки expr = x1 OR ... OR expr = xN
* на выражения expr IN (x1, ..., xN).
*/
void optimizeDisjunctiveEqualityChains();
LogicalExpressionsOptimizer(const LogicalExpressionsOptimizer &) = delete;
LogicalExpressionsOptimizer & operator=(const LogicalExpressionsOptimizer &) = delete;
private:
/** Функция OR с выражением.
*/
struct OrWithExpression
{
OrWithExpression(ASTFunction * or_function_, const std::string & expression_);
bool operator<(const OrWithExpression & rhs) const;
ASTFunction * or_function;
const std::string expression;
};
struct Equalities
{
std::vector<ASTFunction *> functions;
bool is_processed = false;
};
using DisjunctiveEqualityChainsMap = std::map<OrWithExpression, Equalities>;
using DisjunctiveEqualityChain = DisjunctiveEqualityChainsMap::value_type;
private:
/** Собрать информация про все равенства входящие в цепочки OR (не обязательно однородные).
* Эта информация сгруппирована по выражению, которое стоит в левой части равенства.
*/
void collectDisjunctiveEqualityChains();
/** Проверить, что множество равенств expr = x1, ..., expr = xN выполняет два следующих требования:
* 1. Оно не слишком маленькое
* 2. x1, ... xN имеют один и тот же тип
*/
bool mayOptimizeDisjunctiveEqualityChain(const DisjunctiveEqualityChain & chain) const;
/// Вставить выражение IN в OR-цепочку.
void addInExpression(const DisjunctiveEqualityChain & chain);
/// Удалить равенства, которые были заменены выражениями IN.
void cleanupOrExpressions();
/// Удалить выражения OR, которые имеют только один операнд.
void fixBrokenOrExpressions();
private:
using ParentNodes = std::vector<IAST *>;
using FunctionParentMap = std::unordered_map<IAST *, ParentNodes>;
private:
ASTSelectQuery * select_query;
const Settings & settings;
bool hasOptimizedDisjunctiveEqualityChains = false;
/// Информация про OR-цепочки внутри запроса.
DisjunctiveEqualityChainsMap disjunctive_equality_chains_map;
/// Количество обработанных OR-цепочек.
size_t processed_count = 0;
/// Родители функций OR.
FunctionParentMap or_parent_map;
};
}