27 assert(relationMap.find(relation.getName()) == relationMap.end() &&
"double-naming of relations");
28 relationMap[relation.getName()] = &relation;
35 if (isA<ram::Query>(&node)) {
39 encodeIndexPos(*indexSearch);
40 encodeView(indexSearch);
42 encodeIndexPos(*exists);
44 }
else if (
const auto* provExists =
dynamic_cast<const ram::ProvenanceExistenceCheck*
>(&node)) {
45 encodeIndexPos(*provExists);
46 encodeView(provExists);
53 NodePtr NodeGenerator::visitConstant(
const ram::Constant& num) {
54 return mk<Constant>(I_Constant, &num);
57 NodePtr NodeGenerator::visitTupleElement(
const ram::TupleElement& access) {
58 auto tupleId = access.getTupleId();
59 auto elementId = access.getElement();
60 auto newElementId = orderingContext.mapOrder(tupleId, elementId);
61 return mk<TupleElement>(I_TupleElement, &access, tupleId, newElementId);
65 return mk<AutoIncrement>(I_AutoIncrement, &inc);
71 children.push_back(visit(arg));
73 return mk<IntrinsicOperator>(I_IntrinsicOperator, &op, std::move(children));
79 children.push_back(visit(arg));
81 return mk<UserDefinedOperator>(I_UserDefinedOperator, &op, std::move(children));
86 orderingContext.addNewTuple(op.
getTupleId(), arity);
89 children.push_back(visit(arg));
91 children.push_back(visitTupleOperation(op));
92 return mk<NestedIntrinsicOperator>(I_NestedIntrinsicOperator, &op, std::move(children));
98 children.push_back(visit(arg));
100 return mk<PackRecord>(I_PackRecord, &pr, std::move(children));
104 return mk<SubroutineArgument>(I_SubroutineArgument, &arg);
109 return mk<True>(I_True, <rue);
113 return mk<False>(I_False, &lfalse);
117 return mk<Conjunction>(I_Conjunction, &conj, visit(conj.
getLHS()), visit(conj.
getRHS()));
121 return mk<Negation>(I_Negation, &neg, visit(neg.
getOperand()));
126 auto rel = getRelationHandle(relId);
128 return mk<EmptinessCheck>(
type, &emptiness,
rel);
132 size_t relId = encodeRelation(
size.getRelation());
133 auto rel = getRelationHandle(relId);
142 for (
const auto& cur : exists.
getValues()) {
149 return mk<ExistenceCheck>(
type, &exists, isTotal, encodeView(&exists), std::move(superOp),
150 ramRelation.isTemp(), ramRelation.getName());
153 NodePtr NodeGenerator::visitProvenanceExistenceCheck(
const ram::ProvenanceExistenceCheck& provExists) {
154 SuperInstruction superOp = getExistenceSuperInstInfo(provExists);
156 return mk<ProvenanceExistenceCheck>(
type, &provExists, visit(provExists.getChildNodes().back()),
157 encodeView(&provExists), std::move(superOp));
161 return mk<Constraint>(I_Constraint, &relOp, visit(relOp.
getLHS()), visit(relOp.
getRHS()));
169 if (engine.profileEnabled) {
170 return mk<TupleOperation>(I_TupleOperation, &search, visit(search.
getOperation()));
176 orderingContext.addTupleWithDefaultOrder(scan.
getTupleId(), scan);
178 auto rel = getRelationHandle(relId);
180 return mk<Scan>(
type, &scan,
rel, visitTupleOperation(scan));
184 orderingContext.addTupleWithDefaultOrder(pScan.
getTupleId(), pScan);
185 size_t relId = encodeRelation(pScan.
getRelation());
186 auto rel = getRelationHandle(relId);
188 auto res = mk<ParallelScan>(
type, &pScan,
rel, visitTupleOperation(pScan));
189 res->setViewContext(parentQueryViewContext);
194 orderingContext.addTupleWithIndexOrder(iScan.
getTupleId(), iScan);
197 return mk<IndexScan>(
198 type, &iScan,
nullptr, visitTupleOperation(iScan), encodeView(&iScan), std::move(indexOperation));
202 orderingContext.addTupleWithIndexOrder(piscan.
getTupleId(), piscan);
204 size_t relId = encodeRelation(piscan.
getRelation());
205 auto rel = getRelationHandle(relId);
207 auto res = mk<ParallelIndexScan>(
type, &piscan,
rel, visitTupleOperation(piscan), encodeIndexPos(piscan),
208 std::move(indexOperation));
209 res->setViewContext(parentQueryViewContext);
214 orderingContext.addTupleWithDefaultOrder(choice.
getTupleId(), choice);
215 size_t relId = encodeRelation(choice.
getRelation());
216 auto rel = getRelationHandle(relId);
222 orderingContext.addTupleWithDefaultOrder(pChoice.
getTupleId(), pChoice);
223 size_t relId = encodeRelation(pChoice.
getRelation());
224 auto rel = getRelationHandle(relId);
226 auto res = mk<ParallelChoice>(
228 res->setViewContext(parentQueryViewContext);
233 orderingContext.addTupleWithIndexOrder(iChoice.
getTupleId(), iChoice);
236 return mk<IndexChoice>(
type, &iChoice,
nullptr, visit(iChoice.
getCondition()),
237 visitTupleOperation(iChoice), encodeView(&iChoice), std::move(indexOperation));
241 orderingContext.addTupleWithIndexOrder(piChoice.
getTupleId(), piChoice);
243 size_t relId = encodeRelation(piChoice.
getRelation());
244 auto rel = getRelationHandle(relId);
247 visit(piChoice.
getOperation()), encodeIndexPos(piChoice), std::move(indexOperation));
248 res->setViewContext(parentQueryViewContext);
254 return mk<UnpackRecord>(
255 I_UnpackRecord, &unpack, visit(unpack.
getExpression()), visitTupleOperation(unpack));
262 orderingContext.addTupleWithDefaultOrder(aggregate.
getTupleId(), aggregate);
265 orderingContext.addNewTuple(aggregate.
getTupleId(), 1);
266 NodePtr nested = visitTupleOperation(aggregate);
267 size_t relId = encodeRelation(aggregate.
getRelation());
268 auto rel = getRelationHandle(relId);
270 return mk<Aggregate>(
type, &aggregate,
rel, std::move(expr), std::move(cond), std::move(nested));
274 orderingContext.addTupleWithDefaultOrder(pAggregate.
getTupleId(), pAggregate);
277 orderingContext.addNewTuple(pAggregate.
getTupleId(), 1);
278 NodePtr nested = visitTupleOperation(pAggregate);
279 size_t relId = encodeRelation(pAggregate.
getRelation());
280 auto rel = getRelationHandle(relId);
282 auto res = mk<ParallelAggregate>(
283 type, &pAggregate,
rel, std::move(expr), std::move(cond), std::move(nested));
284 res->setViewContext(parentQueryViewContext);
290 orderingContext.addTupleWithIndexOrder(iAggregate.
getTupleId(), iAggregate);
295 NodePtr nested = visitTupleOperation(iAggregate);
296 size_t relId = encodeRelation(iAggregate.
getRelation());
297 auto rel = getRelationHandle(relId);
299 return mk<IndexAggregate>(
type, &iAggregate,
rel, std::move(expr), std::move(cond), std::move(nested),
300 encodeView(&iAggregate), std::move(indexOperation));
304 orderingContext.addTupleWithIndexOrder(piAggregate.
getTupleId(), piAggregate);
309 NodePtr nested = visitTupleOperation(piAggregate);
310 size_t relId = encodeRelation(piAggregate.
getRelation());
311 auto rel = getRelationHandle(relId);
313 auto res = mk<ParallelIndexAggregate>(
type, &piAggregate,
rel, std::move(expr), std::move(cond),
314 std::move(nested), encodeView(&piAggregate), std::move(indexOperation));
315 res->setViewContext(parentQueryViewContext);
329 size_t relId = encodeRelation(project.
getRelation());
330 auto rel = getRelationHandle(relId);
332 return mk<Project>(
type, &project,
rel, std::move(superOp));
337 for (
const auto& value : ret.
getValues()) {
338 children.push_back(visit(value));
340 return mk<SubroutineReturn>(I_SubroutineReturn, &ret, std::move(children));
346 children.push_back(visit(value));
348 return mk<Sequence>(I_Sequence, &seq, std::move(children));
355 children.push_back(visit(value));
357 return mk<Parallel>(I_Parallel, ¶llel, std::move(children));
361 return mk<Loop>(I_Loop, &loop, visit(loop.
getBody()));
364 NodePtr NodeGenerator::visitExit(
const ram::Exit& exit) {
365 return mk<Exit>(I_Exit, &exit, visit(exit.getCondition()));
374 auto subs = engine.tUnit.getProgram().getSubroutines();
375 size_t subroutineId = distance(subs.begin(), subs.find(call.
getName()));
376 return mk<Call>(I_Call, &call, subroutineId);
380 size_t relId = encodeRelation(timer.
getRelation());
381 auto rel = getRelationHandle(relId);
382 return mk<LogRelationTimer>(I_LogRelationTimer, &timer, visit(timer.
getStatement()),
rel);
386 return mk<LogTimer>(I_LogTimer, &timer, visit(timer.
getStatement()));
395 auto rel = getRelationHandle(relId);
397 return mk<Clear>(
type, &clear,
rel);
401 size_t relId = encodeRelation(
size.getRelation());
402 auto rel = getRelationHandle(relId);
403 return mk<LogSize>(I_LogSize, &
size,
rel);
408 auto rel = getRelationHandle(relId);
409 return mk<IO>(I_IO, &io,
rel);
413 std::shared_ptr<ViewContext> viewContext = std::make_shared<ViewContext>();
414 parentQueryViewContext = viewContext;
419 std::vector<const ram::Condition*> freeOfView;
421 next = &
filter->getOperation();
425 for (
auto const& cur : conditions) {
426 bool needView =
false;
428 if (requireView(&node)) {
430 const auto&
rel = getViewRelation(&node);
431 viewContext->addViewInfoForFilter(
432 encodeRelation(
rel), indexTable[&node], encodeView(&node));
437 viewContext->addViewOperationForFilter(visit(*cur));
439 viewContext->addViewFreeOperationForFilter(visit(*cur));
445 if (requireView(&node)) {
446 const auto&
rel = getViewRelation(&node);
447 viewContext->addViewInfoForNested(encodeRelation(
rel), indexTable[&node], encodeView(&node));
451 visitDepthFirst(*next, [&](
const ram::AbstractParallel&) { viewContext->isParallel =
true; });
453 auto res = mk<Query>(I_Query, &query, visit(*next));
454 res->setViewContext(parentQueryViewContext);
458 NodePtr NodeGenerator::visitExtend(
const ram::Extend& extend) {
459 size_t src = encodeRelation(extend.getFirstRelation());
460 size_t target = encodeRelation(extend.getSecondRelation());
461 return mk<Extend>(I_Extend, &extend, src, target);
467 return mk<Swap>(I_Swap, &swap, src, target);
475 fatal(
"unsupported node type: %s",
typeid(node).name());
478 void NodeGenerator::newQueryBlock() {
483 size_t NodeGenerator::getNewRelId() {
487 size_t NodeGenerator::getNextViewId() {
491 template <
class RamNode>
492 size_t NodeGenerator::encodeIndexPos(RamNode& node) {
493 const std::string& name = node.getRelation();
494 auto& orderSet = engine.isa->getIndexes(name);
500 auto i = orderSet.getLexOrderNum(signature);
501 indexTable[&node] =
i;
505 size_t NodeGenerator::encodeView(
const ram::Node* node) {
506 auto pos = viewTable.find(node);
507 if (pos != viewTable.end()) {
510 size_t id = getNextViewId();
511 viewTable[node] =
id;
515 const ram::Relation& NodeGenerator::lookup(
const std::string& relName) {
516 auto it = relationMap.find(relName);
517 assert(it != relationMap.end() &&
"relation not found");
521 size_t NodeGenerator::getArity(
const std::string& relName) {
522 auto rel = lookup(relName);
523 return rel.getArity();
526 size_t NodeGenerator::encodeRelation(
const std::string& relName) {
527 auto pos = relTable.find(relName);
528 if (pos != relTable.end()) {
531 size_t id = getNewRelId();
532 relTable[relName] =
id;
533 engine.createRelation(lookup(relName),
id);
537 RelationHandle* NodeGenerator::getRelationHandle(
const size_t idx) {
538 return engine.relations[idx].get();
541 bool NodeGenerator::requireView(
const ram::Node* node) {
542 if (isA<ram::AbstractExistenceCheck>(node)) {
544 }
else if (isA<ram::IndexOperation>(node)) {
550 const std::string& NodeGenerator::getViewRelation(
const ram::Node* node) {
552 return exist->getRelation();
553 }
else if (
const auto* index =
dynamic_cast<const ram::IndexOperation*
>(node)) {
554 return index->getRelation();
557 fatal(
"The ram::Node does not require a view.");
560 SuperInstruction NodeGenerator::getIndexSuperInstInfo(
const ram::IndexOperation& ramIndex) {
562 auto interpreterRel = encodeRelation(ramIndex.
getRelation());
563 auto indexId = encodeIndexPos(ramIndex);
564 auto order = (*getRelationHandle(interpreterRel))->getIndexOrder(indexId);
567 for (
size_t i = 0;
i < arity; ++
i) {
570 auto&
low = first[order[
i]];
579 if (isA<ram::Constant>(
low)) {
585 if (isA<ram::TupleElement>(
low)) {
588 size_t elementId = lowTuple->getElement();
589 size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
590 indexOperation.
tupleFirst.push_back({
i, tupleId, newElementId});
595 indexOperation.
exprFirst.push_back(std::pair<
size_t, Own<Node>>(
i, visit(
low)));
598 for (
size_t i = 0;
i < arity; ++
i) {
599 auto& hig = second[order[
i]];
608 if (isA<ram::Constant>(hig)) {
609 indexOperation.
second[
i] =
dynamic_cast<ram::Constant*
>(hig)->getConstant();
614 if (isA<ram::TupleElement>(hig)) {
615 auto highTuple =
dynamic_cast<ram::TupleElement*
>(hig);
616 size_t tupleId = highTuple->getTupleId();
617 size_t elementId = highTuple->getElement();
618 size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
619 indexOperation.
tupleSecond.push_back({
i, tupleId, newElementId});
624 indexOperation.
exprSecond.push_back(std::pair<
size_t, Own<Node>>(
i, visit(hig)));
626 return indexOperation;
629 SuperInstruction NodeGenerator::getExistenceSuperInstInfo(
const ram::AbstractExistenceCheck& abstractExist) {
630 auto interpreterRel = encodeRelation(abstractExist.getRelation());
632 if (isA<ram::ExistenceCheck>(&abstractExist)) {
633 indexId = encodeIndexPos(*
dynamic_cast<const ram::ExistenceCheck*
>(&abstractExist));
634 }
else if (isA<ram::ProvenanceExistenceCheck>(&abstractExist)) {
637 fatal(
"Unrecognized ram::AbstractExistenceCheck.");
639 auto order = (*getRelationHandle(interpreterRel))->getIndexOrder(indexId);
640 size_t arity = getArity(abstractExist.getRelation());
641 SuperInstruction superOp(arity);
642 const auto& children = abstractExist.getValues();
643 for (
size_t i = 0;
i < arity; ++
i) {
644 auto& child = children[order[
i]];
654 if (isA<ram::Constant>(child)) {
655 superOp.
first[
i] =
dynamic_cast<ram::Constant*
>(child)->getConstant();
661 if (isA<ram::TupleElement>(child)) {
662 auto tuple =
dynamic_cast<ram::TupleElement*
>(child);
663 size_t tupleId = tuple->getTupleId();
664 size_t elementId = tuple->getElement();
665 size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
666 superOp.
tupleFirst.push_back({
i, tupleId, newElementId});
671 superOp.
exprFirst.push_back(std::pair<
size_t, Own<Node>>(
i, visit(child)));
676 SuperInstruction NodeGenerator::getProjectSuperInstInfo(
const ram::Project& exist) {
677 size_t arity = getArity(exist.getRelation());
678 SuperInstruction superOp(arity);
679 const auto& children = exist.getValues();
680 for (
size_t i = 0;
i < arity; ++
i) {
681 auto& child = children[
i];
683 if (isA<ram::Constant>(child)) {
689 if (isA<ram::TupleElement>(child)) {
691 size_t tupleId =
tuple->getTupleId();
692 size_t elementId =
tuple->getElement();
693 size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
694 superOp.
tupleFirst.push_back({
i, tupleId, newElementId});
699 superOp.
exprFirst.push_back(std::pair<
size_t, Own<Node>>(
i, visit(child)));
706 NodeGenerator::OrderingContext::OrderingContext(NodeGenerator& generator) : generator(generator) {}
709 std::vector<uint32_t> order;
710 for (
size_t i = 0;
i < arity; ++
i) {
711 order.push_back((uint32_t)
i);
716 template <
class RamNode>
718 auto interpreterRel = generator.encodeRelation(node.getRelation());
719 insertOrder(tupleId, (*generator.getRelationHandle(interpreterRel))->getIndexOrder(0));
722 template <
class RamNode>
724 auto interpreterRel = generator.encodeRelation(node.getRelation());
725 auto indexId = generator.encodeIndexPos(node);
726 auto order = (*generator.getRelationHandle(interpreterRel))->getIndexOrder(indexId);
727 insertOrder(tupleId, order);
731 return tupleOrders[tupleId][elementId];
735 if (tupleId >= tupleOrders.size()) {
736 tupleOrders.resize(tupleId + 1);
739 std::vector<uint32_t> decodeOrder(order.
size());
740 for (
size_t i = 0;
i < order.
size(); ++
i) {
741 decodeOrder[order[
i]] =
i;
744 tupleOrders[tupleId] = std::move(decodeOrder);