aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Analyzer/Passes/CNF.h
blob: ec639cd6679742aba01ebec83b31cacafdb2a7b1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#pragma once

#include <Analyzer/HashUtils.h>
#include <Analyzer/IQueryTreeNode.h>

#include <Common/SipHash.h>

#include <Interpreters/Context_fwd.h>

#include <unordered_set>

namespace DB::Analyzer
{

class CNF
{
public:
    struct AtomicFormula
    {
        bool negative = false;
        QueryTreeNodePtrWithHash node_with_hash;

        bool operator==(const AtomicFormula & rhs) const;
        bool operator<(const AtomicFormula & rhs) const;
    };

    // Different hash is generated for different order, so we use std::set
    using OrGroup = std::set<AtomicFormula>;
    using AndGroup = std::set<OrGroup>;

    std::string dump() const;

    static constexpr size_t DEFAULT_MAX_GROWTH_MULTIPLIER = 20;
    static constexpr size_t MAX_ATOMS_WITHOUT_CHECK = 200;

    CNF & transformAtoms(std::function<AtomicFormula(const AtomicFormula &)> fn);
    CNF & transformGroups(std::function<OrGroup(const OrGroup &)> fn);

    CNF & filterAlwaysTrueGroups(std::function<bool(const OrGroup &)> predicate);
    CNF & filterAlwaysFalseAtoms(std::function<bool(const AtomicFormula &)> predicate);

    CNF & reduce();

    void appendGroup(const AndGroup & and_group);

    /// Convert "NOT fn" to a single node representing inverse of "fn"
    CNF & pushNotIntoFunctions(const ContextPtr & context);
    CNF & pullNotOutFunctions(const ContextPtr & context);

    static AtomicFormula pushNotIntoFunction(const AtomicFormula & atom, const ContextPtr & context);

    explicit CNF(AndGroup statements_);

    static std::optional<CNF> tryBuildCNF(const QueryTreeNodePtr & node, ContextPtr context, size_t max_growth_multiplier = DEFAULT_MAX_GROWTH_MULTIPLIER);
    static CNF toCNF(const QueryTreeNodePtr & node, ContextPtr context, size_t max_growth_multiplier = DEFAULT_MAX_GROWTH_MULTIPLIER);

    QueryTreeNodePtr toQueryTree(ContextPtr context) const;

    const auto & getStatements() const
    {
        return statements;
    }
private:
    AndGroup statements;
};

}