42 using ExpressionPair = std::pair<Own<Expression>, Own<Expression>>;
 
   45         const Constraint* binRelOp, 
size_t& element, 
int identifier) {
 
   51                 element = 
lhs->getElement();
 
   52                 return {mk<UndefValue>(), 
clone(
rhs)};
 
   56         if (
const auto* 
rhs = 
dynamic_cast<const TupleElement*
>(&binRelOp->getRHS())) {
 
   59                 element = 
rhs->getElement();
 
   60                 return {
clone(
lhs), mk<UndefValue>()};
 
   67         if (
const auto* 
lhs = 
dynamic_cast<const TupleElement*
>(&binRelOp->getLHS())) {
 
   68             const Expression* 
rhs = &binRelOp->getRHS();
 
   70                 element = 
lhs->getElement();
 
   71                 return {
clone(
rhs), mk<UndefValue>()};
 
   75         if (
const auto* 
rhs = 
dynamic_cast<const TupleElement*
>(&binRelOp->getRHS())) {
 
   76             const Expression* 
lhs = &binRelOp->getLHS();
 
   78                 element = 
rhs->getElement();
 
   79                 return {mk<UndefValue>(), 
clone(
lhs)};
 
   83     return {mk<UndefValue>(), mk<UndefValue>()};
 
   89     if (
auto* binRelOp = 
dynamic_cast<Constraint*
>(c)) {
 
   94             return {mk<UndefValue>(), mk<UndefValue>()};
 
   96             if (
const auto* 
lhs = 
dynamic_cast<const TupleElement*
>(&binRelOp->getLHS())) {
 
   99                     element = 
lhs->getElement();
 
  103             if (
const auto* 
rhs = 
dynamic_cast<const TupleElement*
>(&binRelOp->getRHS())) {
 
  104                 const Expression* 
lhs = &binRelOp->getLHS();
 
  106                     element = 
rhs->getElement();
 
  114     return {mk<UndefValue>(), mk<UndefValue>()};
 
  120     Own<Condition> condition;
 
  122         if (condition != 
nullptr) {
 
  123             condition = mk<Conjunction>(std::move(condition), std::move(c));
 
  125             condition = std::move(c);
 
  132     std::vector<std::unique_ptr<Condition>> toAppend;
 
  133     auto it = conditionList.begin();
 
  134     while (it != conditionList.end()) {
 
  135         auto* binRelOp = 
dynamic_cast<Constraint*
>(it->get());
 
  136         if (binRelOp == 
nullptr) {
 
  141         bool transformable = 
false;
 
  144             if (
const auto* 
lhs = 
dynamic_cast<const TupleElement*
>(&binRelOp->getLHS())) {
 
  147                     transformable = 
true;
 
  150             if (
const auto* 
rhs = 
dynamic_cast<const TupleElement*
>(&binRelOp->getRHS())) {
 
  151                 const Expression* 
lhs = &binRelOp->getLHS();
 
  153                     transformable = 
true;
 
  160             toAppend.emplace_back(
 
  162                             clone(&binRelOp->getLHS()), 
clone(&binRelOp->getRHS())));
 
  164             toAppend.emplace_back(
 
  166                             clone(&binRelOp->getLHS()), 
clone(&binRelOp->getRHS())));
 
  169             it = conditionList.erase(it);
 
  175     std::transform(toAppend.begin(), toAppend.end(), std::back_inserter(conditionList),
 
  176             [](
const std::unique_ptr<Condition>& cond) { return clone(cond); });
 
  179     for (
auto& cond : conditionList) {
 
  181         Own<Expression> lowerExpression;
 
  182         Own<Expression> upperExpression;
 
  189             auto type = attributeTypes[element];
 
  193                 queryPattern.first[element] = std::move(lowerExpression);
 
  194                 queryPattern.second[element] = std::move(upperExpression);
 
  196             } 
else if (
isUndefValue(queryPattern.first[element].get()) &&
 
  198                 queryPattern.first[element] = std::move(lowerExpression);
 
  200             } 
else if (
isUndefValue(queryPattern.second[element].get()) &&
 
  202                 queryPattern.second[element] = std::move(upperExpression);
 
  205             } 
else if (!
isUndefValue(queryPattern.first[element].get()) &&
 
  207                        (*(queryPattern.first[element]) == *(queryPattern.second[element]))) {
 
  213                             souffle::clone(queryPattern.first[element]), std::move(lowerExpression)));
 
  219                             souffle::clone(queryPattern.first[element]), std::move(lowerExpression)));
 
  225                             souffle::clone(queryPattern.first[element]), std::move(upperExpression)));
 
  230             } 
else if (!
isUndefValue(queryPattern.first[element].get()) ||
 
  234                         *lowerExpression == *upperExpression) {
 
  239                                 souffle::clone(lowerExpression), std::move(queryPattern.first[element])));
 
  243                     if (!
isUndefValue(queryPattern.second[element].get())) {
 
  245                                 souffle::clone(upperExpression), std::move(queryPattern.second[element])));
 
  248                     queryPattern.first[element] = std::move(lowerExpression);
 
  249                     queryPattern.second[element] = std::move(upperExpression);
 
  253                     VecOwn<Expression> maxArguments;
 
  254                     maxArguments.push_back(std::move(queryPattern.first[element]));
 
  255                     maxArguments.push_back(std::move(lowerExpression));
 
  257                     queryPattern.first[element] =
 
  258                             mk<IntrinsicOperator>(
getMaxOp(
type), std::move(maxArguments));
 
  262                     VecOwn<Expression> minArguments;
 
  263                     minArguments.push_back(std::move(queryPattern.second[element]));
 
  264                     minArguments.push_back(std::move(upperExpression));
 
  266                     queryPattern.second[element] =
 
  267                             mk<IntrinsicOperator>(
getMinOp(
type), std::move(minArguments));
 
  271             addCondition(std::move(cond));
 
  276     if (condition == 
nullptr) {
 
  277         condition = mk<True>();
 
  283     if (
dynamic_cast<const True*
>(&agg->getCondition()) == 
nullptr) {
 
  287         for (
unsigned int i = 0; 
i < 
rel.getArity(); ++
i) {
 
  288             queryPattern.first.push_back(mk<UndefValue>());
 
  289             queryPattern.second.push_back(mk<UndefValue>());
 
  292         bool indexable = 
false;
 
  296             return mk<IndexAggregate>(
souffle::clone(&agg->getOperation()), agg->getFunction(),
 
  297                     agg->getRelation(), 
souffle::clone(&agg->getExpression()), std::move(condition),
 
  298                     std::move(queryPattern), agg->getTupleId());
 
  305     if (
const auto* 
filter = 
dynamic_cast<const Filter*
>(&scan->getOperation())) {
 
  309         for (
unsigned int i = 0; 
i < 
rel.getArity(); ++
i) {
 
  310             queryPattern.first.push_back(mk<UndefValue>());
 
  311             queryPattern.second.push_back(mk<UndefValue>());
 
  314         bool indexable = 
false;
 
  319             if (!
isTrue(condition.get())) {
 
  320                 op = mk<Filter>(std::move(condition), std::move(op));
 
  322             return mk<IndexScan>(scan->getRelation(), 
identifier, std::move(queryPattern), std::move(op),
 
  323                     scan->getProfileText());
 
  330     if (
const auto* 
filter = 
dynamic_cast<const Filter*
>(&iscan->getOperation())) {
 
  335         strengthenedPattern.first = 
clone(iscan->getRangePattern().first);
 
  336         strengthenedPattern.second = 
clone(iscan->getRangePattern().second);
 
  338         bool indexable = 
false;
 
  347             if (!
isTrue(condition.get())) {
 
  348                 op = mk<Filter>(std::move(condition), std::move(op));
 
  350             return mk<IndexScan>(iscan->getRelation(), 
identifier, std::move(strengthenedPattern),
 
  351                     std::move(op), iscan->getProfileText());
 
  358     bool changed = 
false;
 
  360         std::function<Own<Node>(Own<Node>)> scanRewriter = [&](Own<Node> node) -> Own<Node> {
 
  361             if (
const Scan* scan = 
dynamic_cast<Scan*
>(node.get())) {
 
  366                         node = std::move(op);
 
  372                     node = std::move(op);
 
  374             } 
else if (
const Aggregate* agg = 
dynamic_cast<Aggregate*
>(node.get())) {
 
  377                     node = std::move(op);