This commit is contained in:
Nikita Vasilev 2021-03-05 15:13:00 +03:00
parent 5a2fa1aba7
commit 06454bd912
3 changed files with 79 additions and 5 deletions

View File

@ -102,6 +102,38 @@ ComparisonGraph::ComparisonGraph(const std::vector<ASTPtr> & atomic_formulas)
graph = BuildGraphFromAstsGraph(g);
}
std::pair<bool, bool> ComparisonGraph::findPath(const size_t start, const size_t finish) const
{
// min path : < = -1, =< = 0
const auto inf = std::numeric_limits<int64_t>::max();
const size_t n = graph.vertexes.size();
std::vector<int64_t> dist(n, inf);
dist[start] = 0;
for (size_t k = 0; k < n; ++k)
{
bool has_relaxation = false;
for (size_t v = 0; v < n; ++v)
{
if (dist[v] == inf)
continue;
for (const auto & edge : graph.edges[v])
{
const int64_t weight = edge.type == Edge::Type::LESS ? -1 : 0;
if (dist[edge.to] > dist[v] + weight)
{
dist[edge.to] = dist[v] + weight;
has_relaxation = true;
}
}
}
if (has_relaxation)
break;
}
return {dist[finish] != inf, dist[finish] < 0};
}
ComparisonGraph::CompareResult ComparisonGraph::compare(const ASTPtr & left, const ASTPtr & right) const
{
size_t start = 0;
@ -132,8 +164,17 @@ ComparisonGraph::CompareResult ComparisonGraph::compare(const ASTPtr & left, con
if (start == finish)
return CompareResult::EQUAL;
/// TODO: precalculate in O(n^3) using FloydWarshall algorithm where < = -1 and =< = 0.
/// TODO: precalculate using FloydWarshall O(n^3) algorithm where < = -1 and =< = 0.
/// TODO: use it for less, greater and so on
auto [has_path, is_strict] = findPath(start, finish);
if (has_path)
return is_strict ? CompareResult::GREATER : CompareResult::GREATER_OR_EQUAL;
auto [has_path_r, is_strict_r] = findPath(finish, start);
if (has_path_r)
return is_strict_r ? CompareResult::LESS : CompareResult::LESS_OR_EQUAL;
return CompareResult::UNKNOWN;
}

View File

@ -26,7 +26,6 @@ public:
};
CompareResult compare(const ASTPtr & left, const ASTPtr & right) const;
CompareResult getExpectedCompare(const ASTPtr & ast) const;
std::vector<ASTPtr> getEqual(const ASTPtr & ast) const;
@ -82,6 +81,8 @@ private:
void dfsComponents(
const Graph & reversed_graph, size_t v, std::vector<size_t> & components, const size_t not_visited, const size_t component) const;
std::pair<bool, bool> findPath(const size_t start, const size_t finish) const;
Graph graph;
};

View File

@ -193,7 +193,7 @@ bool checkIfGroupAlwaysTrueGraph(const CNFQuery::OrGroup & group, const Comparis
Poco::Logger::get("GRAPH REASON").information(atom.ast->dumpTree());
Poco::Logger::get("GRAPH REASON").information(std::to_string(static_cast<int>(expected)) + " " + std::to_string(static_cast<int>(result)));
if (expected == ComparisonGraph::CompareResult::UNKNOWN)
if (expected == ComparisonGraph::CompareResult::UNKNOWN || result == ComparisonGraph::CompareResult::UNKNOWN)
return false;
if (expected == result)
@ -232,6 +232,38 @@ bool checkIfAtomAlwaysFalseFullMatch(const CNFQuery::AtomicFormula & atom, const
return false;
}
bool checkIfAtomAlwaysFalseGraph(const CNFQuery::AtomicFormula & atom, const ComparisonGraph & graph)
{
const auto * func = atom.ast->as<ASTFunction>();
if (func && func->arguments->children.size() == 2)
{
/// TODO: special support for !=
const auto expected = getExpectedCompare(atom);
const auto result = graph.compare(func->arguments->children[0], func->arguments->children[1]);
Poco::Logger::get("GRAPH REASON F").information("neg: " + std::to_string(atom.negative));
Poco::Logger::get("GRAPH REASON F").information(atom.ast->dumpTree());
Poco::Logger::get("GRAPH REASON F").information(std::to_string(static_cast<int>(expected)) + " " + std::to_string(static_cast<int>(result)));
if (expected == ComparisonGraph::CompareResult::UNKNOWN || result == ComparisonGraph::CompareResult::UNKNOWN)
return false;
if (expected == result)
return false;
else if (result == ComparisonGraph::CompareResult::EQUAL &&
(expected == ComparisonGraph::CompareResult::LESS_OR_EQUAL || expected == ComparisonGraph::CompareResult::GREATER_OR_EQUAL))
return false;
else if (result == ComparisonGraph::CompareResult::LESS && expected == ComparisonGraph::CompareResult::LESS_OR_EQUAL)
return false;
else if (result == ComparisonGraph::CompareResult::GREATER && expected == ComparisonGraph::CompareResult::GREATER_OR_EQUAL)
return false;
else
return true;
}
return false;
}
void WhereConstraintsOptimizer::perform()
{
if (select_query->where() && metadata_snapshot)
@ -245,8 +277,8 @@ void WhereConstraintsOptimizer::perform()
.filterAlwaysTrueGroups([&constraint_data, &compare_graph](const auto & group) { /// remove always true groups from CNF
return !checkIfGroupAlwaysTrueFullMatch(group, constraint_data) && !checkIfGroupAlwaysTrueGraph(group, compare_graph);
})
.filterAlwaysFalseAtoms([&constraint_data](const auto & atom) { /// remove always false atoms from CNF
return !checkIfAtomAlwaysFalseFullMatch(atom, constraint_data);
.filterAlwaysFalseAtoms([&constraint_data, &compare_graph](const auto & atom) { /// remove always false atoms from CNF
return !checkIfAtomAlwaysFalseFullMatch(atom, constraint_data) && !checkIfAtomAlwaysFalseGraph(atom, compare_graph);
})
.pushNotInFuntions();