Analyzes 'expr' to determine if it can be expressed as a subfield filter. Returns a pair of subfield and filter if so. Otherwise, throws. Supports all expressions supported by exec::ExprToSubfieldFilterParser::leafCallToSubfieldFilter + negations and disjunctions over same subfield. Examples: a = 1 a = 1 OR a > 10 not (a = 1)
| 99 | // a = 1 OR a > 10 |
| 100 | // not (a = 1) |
| 101 | std::pair<common::Subfield, std::unique_ptr<common::Filter>> toSubfieldFilter( |
| 102 | const core::TypedExprPtr& expr, |
| 103 | core::ExpressionEvaluator* evaluator) { |
| 104 | if (auto call = std::dynamic_pointer_cast<const core::CallTypedExpr>(expr)) { |
| 105 | if (call->name() == "or") { |
| 106 | BOLT_CHECK_EQ(call->inputs().size(), 2); |
| 107 | auto left = toSubfieldFilter(call->inputs()[0], evaluator); |
| 108 | auto right = toSubfieldFilter(call->inputs()[1], evaluator); |
| 109 | BOLT_CHECK(left.first == right.first); |
| 110 | return { |
| 111 | std::move(left.first), |
| 112 | exec::ExprToSubfieldFilterParser::makeOrFilter( |
| 113 | std::move(left.second), std::move(right.second))}; |
| 114 | } |
| 115 | |
| 116 | if (call->name() == "not") { |
| 117 | const auto& input = call->inputs()[0]; |
| 118 | if (auto inner = |
| 119 | std::dynamic_pointer_cast<const core::CallTypedExpr>(input)) { |
| 120 | if (auto result = |
| 121 | exec::ExprToSubfieldFilterParser::getInstance() |
| 122 | ->leafCallToSubfieldFilter(*inner, evaluator, true)) { |
| 123 | return std::move(result.value()); |
| 124 | } |
| 125 | } |
| 126 | } else { |
| 127 | if (auto result = |
| 128 | exec::ExprToSubfieldFilterParser::getInstance() |
| 129 | ->leafCallToSubfieldFilter(*call, evaluator, false)) { |
| 130 | return std::move(result.value()); |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | BOLT_UNSUPPORTED( |
| 135 | "Unsupported expression for range filter: {}", expr->toString()); |
| 136 | } |
| 137 | |
| 138 | void flattenTopLevelConjuncts( |
| 139 | const core::TypedExprPtr& expr, |