ClickHouse/src/Interpreters/TreeCNFConverter.h

116 lines
3.0 KiB
C++
Raw Normal View History

2021-01-04 20:55:32 +00:00
#pragma once
#include <Parsers/IAST_fwd.h>
2021-01-05 20:51:19 +00:00
#include <Parsers/ASTLiteral.h>
2021-01-04 20:55:32 +00:00
#include <vector>
#include <set>
#include <unordered_map>
namespace DB
{
class CNFQuery
{
public:
using OrGroup = std::set<ASTPtr>; // Add NOT container???
using AndGroup = std::set<OrGroup>;
2021-01-05 20:51:19 +00:00
CNFQuery(AndGroup && statements_) : statements(std::move(statements_)) { }
2021-01-04 20:55:32 +00:00
template <typename P>
2021-01-05 20:51:19 +00:00
CNFQuery & filterGroups(P predicate) /// delete always true groups
{
2021-01-04 20:55:32 +00:00
AndGroup filtered;
for (const auto & or_group : statements)
{
if (predicate(or_group))
filtered.insert(or_group);
}
std::swap(statements, filtered);
2021-01-05 20:51:19 +00:00
return *this;
2021-01-04 20:55:32 +00:00
}
template <typename P>
2021-01-05 20:51:19 +00:00
CNFQuery & filterAtoms(P predicate) /// delete always false atoms
{
2021-01-04 20:55:32 +00:00
AndGroup filtered;
for (const auto & or_group : statements)
{
OrGroup filtered_group;
2021-01-05 20:51:19 +00:00
for (auto ast : or_group)
{
2021-01-04 20:55:32 +00:00
if (predicate(ast))
filtered_group.insert(ast);
}
if (!filtered_group.empty())
filtered.insert(filtered_group);
2021-01-05 20:51:19 +00:00
else
{
/// all atoms false -> group false -> CNF false
filtered.clear();
filtered_group.clear();
filtered_group.insert(std::make_shared<ASTLiteral>(static_cast<UInt8>(0)));
filtered.insert(filtered_group);
std::swap(statements, filtered);
return *this;
}
2021-01-04 20:55:32 +00:00
}
std::swap(statements, filtered);
2021-01-05 20:51:19 +00:00
return *this;
}
template <typename F>
CNFQuery & transformGroups(F func)
{
AndGroup result;
for (const auto & group : statements)
{
auto new_group = func(group);
if (!new_group.empty())
result.insert(std::move(new_group));
}
std::swap(statements, result);
return *this;
}
template <typename F>
CNFQuery & transformAtoms(F func)
{
transformGroups([func](const OrGroup & group) -> OrGroup
{
OrGroup result;
for (const auto & ast : group)
{
auto new_ast = func(ast);
if (new_ast)
result.insert(std::move(new_ast));
}
return result;
});
return *this;
2021-01-04 20:55:32 +00:00
}
const AndGroup & getStatements() const { return statements; }
std::string dump() const;
2021-01-05 20:51:19 +00:00
/// Converts != -> NOT =; <,>= -> (NOT) <; >,<= -> (NOT) <= for simpler matching
CNFQuery & pullNotOutFunctions();
/// Revert pullNotOutFunctions actions
CNFQuery & pushNotInFuntions();
2021-01-04 20:55:32 +00:00
private:
AndGroup statements;
};
class TreeCNFConverter
{
public:
static CNFQuery toCNF(const ASTPtr & query);
static ASTPtr fromCNF(const CNFQuery & cnf);
};
}