2021-03-04 12:11:43 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <Parsers/IAST_fwd.h>
|
|
|
|
#include <Parsers/ASTLiteral.h>
|
|
|
|
#include <unordered_map>
|
2021-04-03 16:30:49 +00:00
|
|
|
#include <map>
|
2021-03-04 12:11:43 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2021-03-05 12:46:42 +00:00
|
|
|
/*
|
|
|
|
* Graph of relations between terms in constraints.
|
|
|
|
* Allows to compare terms and get equal terms.
|
|
|
|
*/
|
2021-03-04 12:11:43 +00:00
|
|
|
class ComparisonGraph
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ComparisonGraph(const std::vector<ASTPtr> & atomic_formulas);
|
|
|
|
|
|
|
|
enum class CompareResult
|
|
|
|
{
|
|
|
|
LESS,
|
|
|
|
LESS_OR_EQUAL,
|
|
|
|
EQUAL,
|
|
|
|
GREATER_OR_EQUAL,
|
|
|
|
GREATER,
|
2021-05-04 10:47:23 +00:00
|
|
|
NOT_EQUAL,
|
2021-03-04 12:11:43 +00:00
|
|
|
UNKNOWN,
|
|
|
|
};
|
|
|
|
|
2021-05-04 10:47:23 +00:00
|
|
|
static CompareResult getCompareResult(const std::string & name);
|
|
|
|
static CompareResult inverseCompareResult(const CompareResult result);
|
|
|
|
|
2021-03-05 09:54:13 +00:00
|
|
|
CompareResult compare(const ASTPtr & left, const ASTPtr & right) const;
|
2021-03-04 12:11:43 +00:00
|
|
|
|
2021-05-02 19:16:40 +00:00
|
|
|
/// It's possible that left <expected> right
|
|
|
|
bool isPossibleCompare(const CompareResult expected, const ASTPtr & left, const ASTPtr & right) const;
|
|
|
|
|
|
|
|
/// It's always true that left <expected> right
|
|
|
|
bool isAlwaysCompare(const CompareResult expected, const ASTPtr & left, const ASTPtr & right) const;
|
|
|
|
|
2021-03-04 12:11:43 +00:00
|
|
|
std::vector<ASTPtr> getEqual(const ASTPtr & ast) const;
|
2021-03-05 12:46:42 +00:00
|
|
|
std::optional<ASTPtr> getEqualConst(const ASTPtr & ast) const;
|
2021-03-04 12:11:43 +00:00
|
|
|
|
2021-04-26 11:26:54 +00:00
|
|
|
std::optional<std::size_t> getComponentId(const ASTPtr & ast) const;
|
|
|
|
std::vector<ASTPtr> getComponent(const std::size_t id) const;
|
2021-05-03 19:08:26 +00:00
|
|
|
bool hasPath(const size_t left, const size_t right) const;
|
2021-04-26 11:26:54 +00:00
|
|
|
|
2021-04-03 12:12:45 +00:00
|
|
|
/// Find constants lessOrEqual and greaterOrEqual.
|
2021-03-04 12:11:43 +00:00
|
|
|
/// For int and double linear programming can be applied here.
|
2021-04-10 20:46:53 +00:00
|
|
|
/// Returns: {constant, is strict less/greater}
|
|
|
|
std::optional<std::pair<Field, bool>> getConstUpperBound(const ASTPtr & ast) const;
|
|
|
|
std::optional<std::pair<Field, bool>> getConstLowerBound(const ASTPtr & ast) const;
|
2021-03-04 12:11:43 +00:00
|
|
|
|
2021-05-04 18:43:58 +00:00
|
|
|
std::vector<ASTs> getVertices() const;
|
2021-04-28 17:35:51 +00:00
|
|
|
|
2021-03-04 12:11:43 +00:00
|
|
|
private:
|
|
|
|
/// strongly connected component
|
|
|
|
struct EqualComponent
|
|
|
|
{
|
|
|
|
std::vector<ASTPtr> asts;
|
2021-04-10 15:47:50 +00:00
|
|
|
ssize_t constant_index = -1;
|
|
|
|
|
|
|
|
bool hasConstant() const;
|
|
|
|
ASTPtr getConstant() const;
|
|
|
|
void buildConstants();
|
2021-03-04 12:11:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// TODO: move to diff for int and double:
|
|
|
|
/// LESS and LESS_OR_EQUAL with +const or 0 --- ok
|
|
|
|
/// with -const --- not ok
|
|
|
|
/// EQUAL is ok only for 0
|
|
|
|
struct Edge
|
|
|
|
{
|
|
|
|
enum Type
|
|
|
|
{
|
|
|
|
LESS,
|
|
|
|
LESS_OR_EQUAL,
|
|
|
|
EQUAL,
|
|
|
|
};
|
|
|
|
|
|
|
|
Type type;
|
2021-03-05 09:54:13 +00:00
|
|
|
size_t to;
|
2021-03-04 12:11:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Graph
|
|
|
|
{
|
2021-05-04 18:43:58 +00:00
|
|
|
struct ASTHash
|
|
|
|
{
|
|
|
|
size_t operator() (const IAST::Hash & hash) const
|
|
|
|
{
|
2021-03-05 09:54:13 +00:00
|
|
|
return hash.first;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::unordered_map<IAST::Hash, size_t, ASTHash> ast_hash_to_component;
|
2021-05-04 18:43:58 +00:00
|
|
|
std::vector<EqualComponent> vertices;
|
2021-03-04 12:11:43 +00:00
|
|
|
std::vector<std::vector<Edge>> edges;
|
|
|
|
};
|
|
|
|
|
2021-05-06 08:29:24 +00:00
|
|
|
static ASTPtr normalizeAtom(const ASTPtr & atom);
|
|
|
|
static Graph BuildGraphFromAstsGraph(const Graph & asts_graph);
|
2021-03-05 09:54:13 +00:00
|
|
|
|
2021-05-06 08:29:24 +00:00
|
|
|
static Graph reverseGraph(const Graph & asts_graph);
|
|
|
|
static void dfsOrder(const Graph & asts_graph, size_t v, std::vector<bool> & visited, std::vector<size_t> & order);
|
|
|
|
static void dfsComponents(
|
|
|
|
const Graph & reversed_graph, size_t v, std::vector<size_t> & components, const size_t not_visited, const size_t component);
|
2021-03-04 12:11:43 +00:00
|
|
|
|
2021-03-05 12:13:00 +00:00
|
|
|
std::pair<bool, bool> findPath(const size_t start, const size_t finish) const;
|
|
|
|
|
2021-04-03 16:30:49 +00:00
|
|
|
enum class Path
|
|
|
|
{
|
|
|
|
LESS,
|
|
|
|
LESS_OR_EQUAL,
|
|
|
|
};
|
|
|
|
|
2021-05-06 08:29:24 +00:00
|
|
|
static std::map<std::pair<size_t, size_t>, Path> BuildDistsFromGraph(const Graph & g);
|
2021-04-10 20:46:53 +00:00
|
|
|
std::pair<std::vector<ssize_t>, std::vector<ssize_t>> buildConstBounds() const;
|
2021-04-03 16:30:49 +00:00
|
|
|
|
2021-03-04 12:11:43 +00:00
|
|
|
Graph graph;
|
2021-04-03 16:30:49 +00:00
|
|
|
std::map<std::pair<size_t, size_t>, Path> dists;
|
2021-05-04 10:47:23 +00:00
|
|
|
std::set<std::pair<size_t, size_t>> not_equal;
|
2021-04-10 20:46:53 +00:00
|
|
|
std::vector<ssize_t> ast_const_lower_bound;
|
|
|
|
std::vector<ssize_t> ast_const_upper_bound;
|
2021-03-04 12:11:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|