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);