| 185 | } |
| 186 | |
| 187 | ConstraintsDescription::QueryTreeData ConstraintsDescription::getQueryTreeData(const ContextPtr & context, const QueryTreeNodePtr & table_node) const |
| 188 | { |
| 189 | QueryTreeData data; |
| 190 | std::vector<Analyzer::CNFAtomicFormula> atomic_constraints_data; |
| 191 | |
| 192 | QueryAnalysisPass pass(table_node); |
| 193 | |
| 194 | for (const auto & constraint : filterConstraints(ConstraintsDescription::ConstraintType::ALWAYS_TRUE)) |
| 195 | { |
| 196 | auto expr = constraint->as<ASTConstraintDeclaration>()->expr->ptr(); |
| 197 | // Wrap the scalar expression with a function call "equals(SELECT..., 1)". |
| 198 | if (dynamic_cast<ASTSubquery *>(expr.get())) |
| 199 | { |
| 200 | auto func = make_intrusive<ASTFunction>(); |
| 201 | func ->name = "equals"; |
| 202 | func->children.push_back(make_intrusive<ASTExpressionList>()); |
| 203 | auto args = make_intrusive<ASTExpressionList>(); |
| 204 | args->children.push_back(expr); |
| 205 | args->children.push_back(make_intrusive<ASTLiteral>(Field{static_cast<UInt8>(1)})); |
| 206 | func->arguments = args; |
| 207 | expr = func; |
| 208 | } |
| 209 | auto query_tree = buildQueryTree(expr, context); |
| 210 | pass.run(query_tree, context); |
| 211 | |
| 212 | const auto cnf = Analyzer::CNF::toCNF(query_tree, context) |
| 213 | .pullNotOutFunctions(context); |
| 214 | for (const auto & group : cnf.getStatements()) |
| 215 | { |
| 216 | data.cnf_constraints.emplace_back(group.begin(), group.end()); |
| 217 | |
| 218 | if (group.size() == 1) |
| 219 | atomic_constraints_data.emplace_back(*group.begin()); |
| 220 | } |
| 221 | |
| 222 | data.constraints.push_back(std::move(query_tree)); |
| 223 | } |
| 224 | |
| 225 | for (size_t i = 0; i < data.cnf_constraints.size(); ++i) |
| 226 | for (size_t j = 0; j < data.cnf_constraints[i].size(); ++j) |
| 227 | data.query_node_to_atom_ids[data.cnf_constraints[i][j].node_with_hash].push_back({i, j}); |
| 228 | |
| 229 | /// build graph |
| 230 | if (constraints.empty()) |
| 231 | { |
| 232 | data.graph = std::make_unique<ComparisonGraph<QueryTreeNodePtr>>(QueryTreeNodes(), context); |
| 233 | } |
| 234 | else |
| 235 | { |
| 236 | static const NameSet relations = { "equals", "less", "lessOrEquals", "greaterOrEquals", "greater" }; |
| 237 | |
| 238 | QueryTreeNodes constraints_for_graph; |
| 239 | for (const auto & atomic_formula : atomic_constraints_data) |
| 240 | { |
| 241 | Analyzer::CNFAtomicFormula atom{atomic_formula.negative, atomic_formula.node_with_hash.node->clone()}; |
| 242 | atom = Analyzer::CNF::pushNotIntoFunction(atom, context); |
| 243 | |
| 244 | auto * function_node = atom.node_with_hash.node->as<FunctionNode>(); |
no test coverage detected