24 using namespace stream_write_qualified_char_as_number;
29 std::string Relation::getTypeAttributeString(
const std::vector<std::string>& attributeTypes,
30 const std::unordered_set<uint32_t>& attributesUsed)
const {
31 std::stringstream
type;
32 for (
size_t i = 0;
i < attributeTypes.size(); ++
i) {
34 if (attributesUsed.find(
i) != attributesUsed.end()) {
35 switch (attributeTypes[
i][0]) {
36 case 'f':
type <<
'f';
break;
37 case 'u':
type <<
'u';
break;
71 assert(
rel !=
nullptr &&
"relation type not specified");
73 rel->computeIndices();
87 return "t_info<" + std::to_string(getArity()) +
">";
100 computedIndices = {};
105 return "t_nullaries";
122 assert(!inds.empty() &&
"no full index in relation");
126 for (
auto& ind : inds) {
128 std::set<int> curIndexElems(ind.begin(), ind.end());
136 for (
size_t i = 0;
i < getArity() -
relation.getAuxiliaryArity();
i++) {
137 if (curIndexElems.find(
i) == curIndexElems.end()) {
142 if (curIndexElems.find(getArity() -
relation.getAuxiliaryArity() + 1) != curIndexElems.end()) {
143 ind.erase(std::find(ind.begin(), ind.end(), getArity() -
relation.getAuxiliaryArity() + 1));
146 if (curIndexElems.find(getArity() -
relation.getAuxiliaryArity()) != curIndexElems.end()) {
147 ind.erase(std::find(ind.begin(), ind.end(), getArity() -
relation.getAuxiliaryArity()));
151 ind.push_back(getArity() -
relation.getAuxiliaryArity() + 1);
152 ind.push_back(getArity() -
relation.getAuxiliaryArity());
154 }
else if (ind.size() == getArity()) {
155 masterIndex = index_nr;
159 assert(masterIndex < inds.size() &&
"no full index in relation");
160 computedIndices = inds;
166 std::unordered_set<uint32_t> attributesUsed;
167 for (
auto& ind : getIndices()) {
168 for (
auto& attr : ind) {
169 attributesUsed.insert(attr);
173 std::stringstream res;
174 res <<
"t_btree_" << getTypeAttributeString(
relation.getAttributeTypes(), attributesUsed);
176 for (
auto& ind : getIndices()) {
177 res <<
"__" <<
join(ind,
"_");
180 for (
auto& search : getMinIndexSelection().getSearches()) {
181 res <<
"__" << search;
189 size_t arity = getArity();
190 size_t auxiliaryArity =
relation.getAuxiliaryArity();
192 const auto& inds = getIndices();
193 size_t numIndexes = inds.size();
194 std::map<MinIndexSelection::LexOrder, int> indexToNumMap;
197 out <<
"struct " << getTypeName() <<
" {\n";
198 out <<
"static constexpr Relation::arity_type Arity = " << arity <<
";\n";
201 out <<
"using t_tuple = Tuple<RamDomain, " << arity <<
">;\n";
205 out <<
"struct updater_" << getTypeName() <<
" {\n";
206 out <<
"void update(t_tuple& old_t, const t_tuple& new_t) {\n";
208 for (
size_t i = arity - auxiliaryArity;
i < arity;
i++) {
209 out <<
"old_t[" <<
i <<
"] = new_t[" <<
i <<
"];\n";
217 for (
size_t i = 0;
i < inds.size();
i++) {
220 if (
i < getMinIndexSelection().getAllOrders().
size()) {
221 indexToNumMap[getMinIndexSelection().getAllOrders()[
i]] =
i;
224 std::vector<std::string> typecasts;
225 typecasts.reserve(
types.size());
229 case 'f': typecasts.push_back(
"ramBitCast<RamFloat>");
break;
230 case 'u': typecasts.push_back(
"ramBitCast<RamUnsigned>");
break;
231 default: typecasts.push_back(
"ramBitCast<RamSigned>");
235 auto genstruct = [&](std::string name,
size_t bound) {
236 out <<
"struct " << name <<
"{\n";
237 out <<
" int operator()(const t_tuple& a, const t_tuple& b) const {\n";
239 std::function<void(
size_t)> gencmp = [&](
size_t i) {
240 size_t attrib = ind[
i];
241 const auto& typecast = typecasts[attrib];
243 out <<
"(" << typecast <<
"(a[" << attrib <<
"]) < " << typecast <<
"(b[" << attrib
244 <<
"])) ? -1 : (" << typecast <<
"(a[" << attrib <<
"]) > " << typecast <<
"(b[" << attrib
255 out <<
"bool less(const t_tuple& a, const t_tuple& b) const {\n";
257 std::function<void(
size_t)> genless = [&](
size_t i) {
258 size_t attrib = ind[
i];
259 const auto& typecast = typecasts[attrib];
261 out <<
"(" << typecast <<
"(a[" << attrib <<
"]) < " << typecast <<
"(b[" << attrib <<
"]))";
263 out <<
"|| (" << typecast <<
"(a[" << attrib <<
"]) == " << typecast <<
"(b[" << attrib
271 out <<
"bool equal(const t_tuple& a, const t_tuple& b) const {\n";
273 std::function<void(
size_t)> geneq = [&](
size_t i) {
274 size_t attrib = ind[
i];
275 const auto& typecast = typecasts[attrib];
277 out <<
"(" << typecast <<
"(a[" << attrib <<
"]) == " << typecast <<
"(b[" << attrib <<
"]))";
288 std::string
comparator =
"t_comparator_" + std::to_string(
i);
295 std::string comparator_aux;
296 if (provenanceIndexNumbers.find(
i) == provenanceIndexNumbers.end()) {
298 comparator_aux =
"t_comparator_" + std::to_string(
i) +
"_aux";
299 genstruct(comparator_aux, ind.size() - auxiliaryArity);
304 out <<
"using t_ind_" <<
i <<
" = btree_set<t_tuple," <<
comparator
305 <<
",std::allocator<t_tuple>,256,typename "
306 "souffle::detail::default_strategy<t_tuple>::type,"
307 << comparator_aux <<
",updater_" << getTypeName() <<
">;\n";
309 if (ind.size() == arity) {
310 out <<
"using t_ind_" <<
i <<
" = btree_set<t_tuple," <<
comparator <<
">;\n";
313 out <<
"using t_ind_" <<
i <<
" = btree_multiset<t_tuple," <<
comparator <<
">;\n";
316 out <<
"t_ind_" <<
i <<
" ind_" <<
i <<
";\n";
320 out <<
"using iterator = t_ind_" << masterIndex <<
"::iterator;\n";
323 out <<
"struct context {\n";
324 for (
size_t i = 0;
i < numIndexes;
i++) {
325 out <<
"t_ind_" <<
i <<
"::operation_hints hints_" <<
i <<
"_lower"
327 out <<
"t_ind_" <<
i <<
"::operation_hints hints_" <<
i <<
"_upper"
331 out <<
"context createContext() { return context(); }\n";
334 out <<
"bool insert(const t_tuple& t) {\n";
335 out <<
"context h;\n";
336 out <<
"return insert(t, h);\n";
339 out <<
"bool insert(const t_tuple& t, context& h) {\n";
340 out <<
"if (ind_" << masterIndex <<
".insert(t, h.hints_" << masterIndex <<
"_lower"
342 for (
size_t i = 0;
i < numIndexes;
i++) {
343 if (
i != masterIndex && provenanceIndexNumbers.find(
i) == provenanceIndexNumbers.end()) {
344 out <<
"ind_" <<
i <<
".insert(t, h.hints_" <<
i <<
"_lower"
348 out <<
"return true;\n";
349 out <<
"} else return false;\n";
352 out <<
"bool insert(const RamDomain* ramDomain) {\n";
353 out <<
"RamDomain data[" << arity <<
"];\n";
354 out <<
"std::copy(ramDomain, ramDomain + " << arity <<
", data);\n";
355 out <<
"const t_tuple& tuple = reinterpret_cast<const t_tuple&>(data);\n";
356 out <<
"context h;\n";
357 out <<
"return insert(tuple, h);\n";
360 std::vector<std::string> decls;
361 std::vector<std::string> params;
362 for (
size_t i = 0;
i < arity;
i++) {
363 decls.push_back(
"RamDomain a" + std::to_string(
i));
364 params.push_back(
"a" + std::to_string(
i));
366 out <<
"bool insert(" <<
join(decls,
",") <<
") {\n";
367 out <<
"RamDomain data[" << arity <<
"] = {" <<
join(params,
",") <<
"};\n";
368 out <<
"return insert(data);\n";
372 out <<
"bool contains(const t_tuple& t, context& h) const {\n";
373 out <<
"return ind_" << masterIndex <<
".contains(t, h.hints_" << masterIndex <<
"_lower"
377 out <<
"bool contains(const t_tuple& t) const {\n";
378 out <<
"context h;\n";
379 out <<
"return contains(t, h);\n";
383 out <<
"std::size_t size() const {\n";
384 out <<
"return ind_" << masterIndex <<
".size();\n";
388 out <<
"iterator find(const t_tuple& t, context& h) const {\n";
389 out <<
"return ind_" << masterIndex <<
".find(t, h.hints_" << masterIndex <<
"_lower"
393 out <<
"iterator find(const t_tuple& t) const {\n";
394 out <<
"context h;\n";
395 out <<
"return find(t, h);\n";
400 <<
"(const t_tuple& /* lower */, const t_tuple& /* upper */, context& /* h */) const "
403 out <<
"return range<iterator>(ind_" << masterIndex <<
".begin(),ind_" << masterIndex <<
".end());\n";
407 <<
"(const t_tuple& /* lower */, const t_tuple& /* upper */) const {\n";
409 out <<
"return range<iterator>(ind_" << masterIndex <<
".begin(),ind_" << masterIndex <<
".end());\n";
413 for (
auto search : getMinIndexSelection().getSearches()) {
414 auto& lexOrder = getMinIndexSelection().getLexOrder(search);
415 size_t indNum = indexToNumMap[lexOrder];
417 out <<
"range<t_ind_" << indNum <<
"::iterator> lowerUpperRange_" << search;
418 out <<
"(const t_tuple& lower, const t_tuple& upper, context& h) const {\n";
422 for (
size_t column = 0; column < arity; column++) {
423 if (search[column] == analysis::AttributeConstraint::Equal) {
428 out <<
"t_comparator_" << indNum <<
" comparator;\n";
429 out <<
"int cmp = comparator(lower, upper);\n";
432 if (eqSize == arity) {
434 out <<
"if (cmp == 0) {\n";
435 out <<
" auto pos = ind_" << indNum <<
".find(lower, h.hints_" << indNum <<
"_lower);\n";
436 out <<
" auto fin = ind_" << indNum <<
".end();\n";
437 out <<
" if (pos != fin) {fin = pos; ++fin;}\n";
438 out <<
" return make_range(pos, fin);\n";
442 out <<
"if (cmp > 0) {\n";
443 out <<
" return make_range(ind_" << indNum <<
".end(), ind_" << indNum <<
".end());\n";
446 out <<
"return make_range(ind_" << indNum <<
".lower_bound(lower, h.hints_" << indNum <<
"_lower"
447 <<
"), ind_" << indNum <<
".upper_bound(upper, h.hints_" << indNum <<
"_upper"
452 out <<
"range<t_ind_" << indNum <<
"::iterator> lowerUpperRange_" << search;
453 out <<
"(const t_tuple& lower, const t_tuple& upper) const {\n";
455 out <<
"context h;\n";
456 out <<
"return lowerUpperRange_" << search <<
"(lower,upper,h);\n";
461 out <<
"bool empty() const {\n";
462 out <<
"return ind_" << masterIndex <<
".empty();\n";
466 out <<
"std::vector<range<iterator>> partition() const {\n";
467 out <<
"return ind_" << masterIndex <<
".getChunks(400);\n";
471 out <<
"void purge() {\n";
472 for (
size_t i = 0;
i < numIndexes;
i++) {
473 out <<
"ind_" <<
i <<
".clear();\n";
478 out <<
"iterator begin() const {\n";
479 out <<
"return ind_" << masterIndex <<
".begin();\n";
482 out <<
"iterator end() const {\n";
483 out <<
"return ind_" << masterIndex <<
".end();\n";
487 if (!provenanceIndexNumbers.empty()) {
488 out <<
"void copyIndex() {\n";
489 out <<
"for (auto const &cur : ind_" << masterIndex <<
") {\n";
490 for (
auto const i : provenanceIndexNumbers) {
491 out <<
"ind_" <<
i <<
".insert(cur);\n";
498 out <<
"void printStatistics(std::ostream& o) const {\n";
499 for (
size_t i = 0;
i < numIndexes;
i++) {
500 out <<
"o << \" arity " << arity <<
" direct b-tree index " <<
i <<
" lex-order " << inds[
i]
502 out <<
"ind_" <<
i <<
".printStats(o);\n";
514 assert(!isProvenance &&
"indirect indexes cannot used for provenance");
520 assert(!inds.empty() &&
"no full index in relation");
523 for (
size_t i = 0;
i < inds.size();
i++) {
525 if (ind.size() == getArity()) {
530 assert(masterIndex < inds.size() &&
"no full index in relation");
531 computedIndices = inds;
537 std::unordered_set<uint32_t> attributesUsed;
538 for (
auto& ind : getIndices()) {
539 for (
auto& attr : ind) {
540 attributesUsed.insert(attr);
544 std::stringstream res;
545 res <<
"t_btree_" << getTypeAttributeString(
relation.getAttributeTypes(), attributesUsed);
547 for (
auto& ind : getIndices()) {
548 res <<
"__" <<
join(ind,
"_");
551 for (
auto& search : getMinIndexSelection().getSearches()) {
552 res <<
"__" << search;
560 size_t arity = getArity();
561 const auto& inds = getIndices();
563 size_t numIndexes = inds.size();
564 std::map<MinIndexSelection::LexOrder, int> indexToNumMap;
567 out <<
"struct " << getTypeName() <<
" {\n";
568 out <<
"static constexpr Relation::arity_type Arity = " << arity <<
";\n";
571 out <<
"using t_tuple = Tuple<RamDomain, " << arity <<
">;\n";
574 out <<
"Table<t_tuple> dataTable;\n";
575 out <<
"Lock insert_lock;\n";
578 for (
size_t i = 0;
i < inds.size();
i++) {
581 if (
i < getMinIndexSelection().getAllOrders().
size()) {
582 indexToNumMap[getMinIndexSelection().getAllOrders()[
i]] =
i;
585 std::vector<std::string> typecasts;
586 typecasts.reserve(
types.size());
590 case 'f': typecasts.push_back(
"ramBitCast<RamFloat>");
break;
591 case 'u': typecasts.push_back(
"ramBitCast<RamUnsigned>");
break;
592 default: typecasts.push_back(
"ramBitCast<RamSigned>");
596 std::string
comparator =
"t_comparator_" + std::to_string(
i);
599 out <<
" int operator()(const t_tuple *a, const t_tuple *b) const {\n";
601 std::function<void(
size_t)> gencmp = [&](
size_t i) {
602 size_t attrib = ind[
i];
603 const auto& typecast = typecasts[attrib];
604 out <<
"(" << typecast <<
"((*a)[" << attrib <<
"]) <" << typecast <<
" ((*b)[" << attrib
605 <<
"])) ? -1 : ((" << typecast <<
"((*a)[" << attrib <<
"]) > " << typecast <<
"((*b)["
606 << attrib <<
"])) ? 1 :(";
607 if (
i + 1 < ind.size()) {
616 out <<
"bool less(const t_tuple *a, const t_tuple *b) const {\n";
618 std::function<void(
size_t)> genless = [&](
size_t i) {
619 size_t attrib = ind[
i];
620 const auto& typecast = typecasts[attrib];
621 out << typecast <<
" ((*a)[" << attrib <<
"]) < " << typecast <<
"((*b)[" << attrib <<
"])";
622 if (
i + 1 < ind.size()) {
623 out <<
"|| (" << typecast <<
"((*a)[" << attrib <<
"]) == " << typecast <<
"((*b)[" << attrib
631 out <<
"bool equal(const t_tuple *a, const t_tuple *b) const {\n";
633 std::function<void(
size_t)> geneq = [&](
size_t i) {
634 size_t attrib = ind[
i];
635 const auto& typecast = typecasts[attrib];
636 out << typecast <<
"((*a)[" << attrib <<
"]) == " << typecast <<
"((*b)[" << attrib <<
"])";
637 if (
i + 1 < ind.size()) {
646 if (ind.size() == arity) {
647 out <<
"using t_ind_" <<
i <<
" = btree_set<const t_tuple*," <<
comparator <<
">;\n";
649 out <<
"using t_ind_" <<
i <<
" = btree_multiset<const t_tuple*," <<
comparator <<
">;\n";
652 out <<
"t_ind_" <<
i <<
" ind_" <<
i <<
";\n";
656 for (
size_t i = 0;
i < numIndexes;
i++) {
657 out <<
"using iterator_" <<
i <<
" = IterDerefWrapper<typename t_ind_" <<
i <<
"::iterator>;\n";
659 out <<
"using iterator = iterator_" << masterIndex <<
";\n";
662 out <<
"struct context {\n";
663 for (
size_t i = 0;
i < numIndexes;
i++) {
664 out <<
"t_ind_" <<
i <<
"::operation_hints hints_" <<
i <<
"_lower;\n";
665 out <<
"t_ind_" <<
i <<
"::operation_hints hints_" <<
i <<
"_upper;\n";
668 out <<
"context createContext() { return context(); }\n";
671 out <<
"bool insert(const t_tuple& t) {\n";
672 out <<
"context h;\n";
673 out <<
"return insert(t, h);\n";
676 out <<
"bool insert(const t_tuple& t, context& h) {\n";
677 out <<
"const t_tuple* masterCopy = nullptr;\n";
679 out <<
"auto lease = insert_lock.acquire();\n";
680 out <<
"if (contains(t, h)) return false;\n";
681 out <<
"masterCopy = &dataTable.insert(t);\n";
682 out <<
"ind_" << masterIndex <<
".insert(masterCopy, h.hints_" << masterIndex <<
"_lower);\n";
684 for (
size_t i = 0;
i < numIndexes;
i++) {
685 if (
i != masterIndex) {
686 out <<
"ind_" <<
i <<
".insert(masterCopy, h.hints_" <<
i <<
"_lower"
690 out <<
"return true;\n";
693 out <<
"bool insert(const RamDomain* ramDomain) {\n";
694 out <<
"RamDomain data[" << arity <<
"];\n";
695 out <<
"std::copy(ramDomain, ramDomain + " << arity <<
", data);\n";
696 out <<
"const t_tuple& tuple = reinterpret_cast<const t_tuple&>(data);\n";
697 out <<
"context h;\n";
698 out <<
"return insert(tuple, h);\n";
701 std::vector<std::string> decls;
702 std::vector<std::string> params;
703 for (
size_t i = 0;
i < arity;
i++) {
704 decls.push_back(
"RamDomain a" + std::to_string(
i));
705 params.push_back(
"a" + std::to_string(
i));
707 out <<
"bool insert(" <<
join(decls,
",") <<
") {\n";
708 out <<
"RamDomain data[" << arity <<
"] = {" <<
join(params,
",") <<
"};\n";
709 out <<
"return insert(data);\n";
713 out <<
"bool contains(const t_tuple& t, context& h) const {\n";
714 out <<
"return ind_" << masterIndex <<
".contains(&t, h.hints_" << masterIndex <<
"_lower"
718 out <<
"bool contains(const t_tuple& t) const {\n";
719 out <<
"context h;\n";
720 out <<
"return contains(t, h);\n";
724 out <<
"std::size_t size() const {\n";
725 out <<
"return ind_" << masterIndex <<
".size();\n";
729 out <<
"iterator find(const t_tuple& t, context& h) const {\n";
730 out <<
"return ind_" << masterIndex <<
".find(&t, h.hints_" << masterIndex <<
"_lower"
734 out <<
"iterator find(const t_tuple& t) const {\n";
735 out <<
"context h;\n";
736 out <<
"return find(t, h);\n";
740 out <<
"range<iterator> lowerUpperRange_0(const t_tuple& lower, const t_tuple& upper, context& h) const "
743 out <<
"return range<iterator>(ind_" << masterIndex <<
".begin(),ind_" << masterIndex <<
".end());\n";
746 out <<
"range<iterator> lowerUpperRange_0(const t_tuple& lower, const t_tuple& upper) const {\n";
748 out <<
"return range<iterator>(ind_" << masterIndex <<
".begin(),ind_" << masterIndex <<
".end());\n";
752 for (
auto search : getMinIndexSelection().getSearches()) {
753 auto& lexOrder = getMinIndexSelection().getLexOrder(search);
754 size_t indNum = indexToNumMap[lexOrder];
756 out <<
"range<iterator_" << indNum <<
"> lowerUpperRange_" << search;
757 out <<
"(const t_tuple& lower, const t_tuple& upper, context& h) const {\n";
761 for (
size_t column = 0; column < arity; column++) {
762 if (search[column] == analysis::AttributeConstraint::Equal) {
767 out <<
"t_comparator_" << indNum <<
" comparator;\n";
768 out <<
"int cmp = comparator(&lower, &upper);\n";
771 if (eqSize == arity) {
773 out <<
"if (cmp == 0) {\n";
774 out <<
" auto pos = find(lower, h);\n";
775 out <<
" auto fin = end();\n";
776 out <<
" if (pos != fin) {fin = pos; ++fin;}\n";
777 out <<
" return make_range(pos, fin);\n";
781 out <<
"if (cmp > 0) {\n";
782 out <<
" return range<iterator_" << indNum <<
">(ind_" << indNum <<
".end(), ind_" << indNum
787 out <<
"return range<iterator_" << indNum <<
">(ind_" << indNum <<
".lower_bound(&lower, h.hints_"
788 << indNum <<
"_lower"
789 <<
"), ind_" << indNum <<
".upper_bound(&upper, h.hints_" << indNum <<
"_upper"
794 out <<
"range<iterator_" << indNum <<
"> lowerUpperRange_" << search;
795 out <<
"(const t_tuple& lower, const t_tuple& upper) const {\n";
797 out <<
"context h;\n";
798 out <<
"return lowerUpperRange_" << search <<
"(lower, upper, h);\n";
803 out <<
"bool empty() const {\n";
804 out <<
"return ind_" << masterIndex <<
".empty();\n";
808 out <<
"std::vector<range<iterator>> partition() const {\n";
809 out <<
"std::vector<range<iterator>> res;\n";
810 out <<
"for (const auto& cur : ind_" << masterIndex <<
".getChunks(400)) {\n";
811 out <<
" res.push_back(make_range(derefIter(cur.begin()), derefIter(cur.end())));\n";
813 out <<
"return res;\n";
817 out <<
"void purge() {\n";
818 for (
size_t i = 0;
i < numIndexes;
i++) {
819 out <<
"ind_" <<
i <<
".clear();\n";
821 out <<
"dataTable.clear();\n";
825 out <<
"iterator begin() const {\n";
826 out <<
"return ind_" << masterIndex <<
".begin();\n";
829 out <<
"iterator end() const {\n";
830 out <<
"return ind_" << masterIndex <<
".end();\n";
834 out <<
"void printStatistics(std::ostream& o) const {\n";
835 for (
size_t i = 0;
i < numIndexes;
i++) {
836 out <<
"o << \" arity " << arity <<
" indirect b-tree index " <<
i <<
" lex-order " << inds[
i]
838 out <<
"ind_" <<
i <<
".printStats(o);\n";
850 assert(!isProvenance &&
"bries cannot be used with provenance");
856 assert(!inds.empty() &&
"No full index in relation");
859 for (
auto& ind : inds) {
860 if (ind.size() != getArity()) {
862 std::set<int> curIndexElems(ind.begin(), ind.end());
865 for (
size_t i = 0;
i < getArity();
i++) {
866 if (curIndexElems.find(
i) == curIndexElems.end()) {
872 assert(ind.size() == getArity() &&
"index is not a full");
876 computedIndices = inds;
882 std::unordered_set<uint32_t> attributesUsed;
883 for (
auto& ind : getIndices()) {
884 for (
auto& attr : ind) {
885 attributesUsed.insert(attr);
889 std::stringstream res;
890 res <<
"t_brie_" << getTypeAttributeString(
relation.getAttributeTypes(), attributesUsed);
892 for (
auto& ind : getIndices()) {
893 res <<
"__" <<
join(ind,
"_");
896 for (
auto& search : getMinIndexSelection().getSearches()) {
897 res <<
"__" << search;
905 size_t arity = getArity();
906 const auto& inds = getIndices();
907 size_t numIndexes = inds.size();
908 std::map<MinIndexSelection::LexOrder, int> indexToNumMap;
911 out <<
"struct " << getTypeName() <<
" {\n";
912 out <<
"static constexpr Relation::arity_type Arity = " << arity <<
";\n";
915 for (
size_t i = 0;
i < inds.size();
i++) {
916 if (
i < getMinIndexSelection().getAllOrders().
size()) {
917 indexToNumMap[getMinIndexSelection().getAllOrders()[
i]] =
i;
919 out <<
"using t_ind_" <<
i <<
" = Trie<" << inds[
i].size() <<
">;\n";
920 out <<
"t_ind_" <<
i <<
" ind_" <<
i <<
";\n";
922 out <<
"using t_tuple = t_ind_" << masterIndex <<
"::entry_type;\n";
925 for (
size_t i = 0;
i < numIndexes;
i++) {
927 out <<
"class iterator_" <<
i <<
" : public std::iterator<std::forward_iterator_tag, t_tuple> {\n";
928 out <<
" using nested_iterator = typename t_ind_" <<
i <<
"::iterator;\n";
929 out <<
" nested_iterator nested;\n";
930 out <<
" t_tuple value;\n";
933 out <<
" iterator_" <<
i <<
"() = default;\n";
934 out <<
" iterator_" <<
i <<
"(const nested_iterator& iter) : nested(iter), value(orderOut_" <<
i
936 out <<
" iterator_" <<
i <<
"(const iterator_" <<
i <<
"& other) = default;\n";
937 out <<
" iterator_" <<
i <<
"& operator=(const iterator_" <<
i <<
"& other) = default;\n";
939 out <<
" bool operator==(const iterator_" <<
i <<
"& other) const {\n";
940 out <<
" return nested == other.nested;\n";
943 out <<
" bool operator!=(const iterator_" <<
i <<
"& other) const {\n";
944 out <<
" return !(*this == other);\n";
947 out <<
" const t_tuple& operator*() const {\n";
948 out <<
" return value;\n";
951 out <<
" const t_tuple* operator->() const {\n";
952 out <<
" return &value;\n";
955 out <<
" iterator_" <<
i <<
"& operator++() {\n";
956 out <<
" ++nested;\n";
957 out <<
" value = orderOut_" <<
i <<
"(*nested);\n";
958 out <<
" return *this;\n";
962 out <<
"using iterator = iterator_" << masterIndex <<
";\n";
965 out <<
"struct context {\n";
966 for (
size_t i = 0;
i < numIndexes;
i++) {
967 out <<
"t_ind_" <<
i <<
"::op_context hints_" <<
i <<
";\n";
970 out <<
"context createContext() { return context(); }\n";
973 out <<
"bool insert(const t_tuple& t) {\n";
974 out <<
"context h;\n";
975 out <<
"return insert(t, h);\n";
978 out <<
"bool insert(const t_tuple& t, context& h) {\n";
979 out <<
"if (ind_" << masterIndex <<
".insert(orderIn_" << masterIndex <<
"(t), h.hints_" << masterIndex
981 for (
size_t i = 0;
i < numIndexes;
i++) {
982 if (
i != masterIndex) {
983 out <<
"ind_" <<
i <<
".insert(orderIn_" <<
i <<
"(t), h.hints_" <<
i <<
");\n";
986 out <<
"return true;\n";
987 out <<
"} else return false;\n";
990 out <<
"bool insert(const RamDomain* ramDomain) {\n";
991 out <<
"RamDomain data[" << arity <<
"];\n";
992 out <<
"std::copy(ramDomain, ramDomain + " << arity <<
", data);\n";
993 out <<
"const t_tuple& tuple = reinterpret_cast<const t_tuple&>(data);\n";
994 out <<
"context h;\n";
995 out <<
"return insert(tuple, h);\n";
999 std::vector<std::string> decls;
1000 std::vector<std::string> params;
1001 for (
size_t i = 0;
i < arity;
i++) {
1002 decls.push_back(
"RamDomain a" + std::to_string(
i));
1003 params.push_back(
"a" + std::to_string(
i));
1005 out <<
"bool insert(" <<
join(decls,
",") <<
") {\nRamDomain data[";
1006 out << arity <<
"] = {" <<
join(params,
",") <<
"};\n";
1007 out <<
"return insert(data);\n";
1011 out <<
"bool contains(const t_tuple& t, context& h) const {\n";
1012 out <<
"return ind_" << masterIndex <<
".contains(orderIn_" << masterIndex <<
"(t), h.hints_"
1013 << masterIndex <<
");\n";
1016 out <<
"bool contains(const t_tuple& t) const {\n";
1017 out <<
"context h;\n";
1018 out <<
"return contains(t, h);\n";
1022 out <<
"std::size_t size() const {\n";
1023 out <<
"return ind_" << masterIndex <<
".size();\n";
1028 out <<
"iterator find(const t_tuple& t, context& h) const {\n";
1029 out <<
"return ind_" << masterIndex <<
".find(orderIn_" << masterIndex <<
"(t), h.hints_"
1030 << masterIndex <<
");\n";
1033 out <<
"iterator find(const t_tuple& t) const {\n";
1034 out <<
"context h;\n";
1035 out <<
"return find(t, h);\n";
1040 out <<
"range<iterator> lowerUpperRange_0(const t_tuple& lower, const t_tuple& upper, context& h) const "
1042 out <<
"return range<iterator>(ind_" << masterIndex <<
".begin(),ind_" << masterIndex <<
".end());\n";
1045 out <<
"range<iterator> lowerUpperRange_0(const t_tuple& lower, const t_tuple& upper) const {\n";
1046 out <<
"return range<iterator>(ind_" << masterIndex <<
".begin(),ind_" << masterIndex <<
".end());\n";
1050 for (
auto search : getMinIndexSelection().getSearches()) {
1051 auto& lexOrder = getMinIndexSelection().getLexOrder(search);
1052 size_t indNum = indexToNumMap[lexOrder];
1054 out <<
"range<iterator_" << indNum <<
"> lowerUpperRange_" << search;
1055 out <<
"(const t_tuple& lower, const t_tuple& upper, context& h) const {\n";
1059 for (
size_t i = 0;
i < arity;
i++) {
1060 if (search[
i] != analysis::AttributeConstraint::None) {
1065 out <<
"auto r = ind_" << indNum <<
".template getBoundaries<" << indSize <<
">(orderIn_" << indNum
1066 <<
"(lower), h.hints_" << indNum <<
");\n";
1067 out <<
"return make_range(iterator_" << indNum <<
"(r.begin()), iterator_" << indNum
1071 out <<
"range<iterator_" << indNum <<
"> lowerUpperRange_" << search;
1072 out <<
"(const t_tuple& lower, const t_tuple& upper) const {\n";
1073 out <<
"context h; return lowerUpperRange_" << search <<
"(lower,upper, h);\n";
1078 out <<
"bool empty() const {\n";
1079 out <<
"return ind_" << masterIndex <<
".empty();\n";
1083 out <<
"std::vector<range<iterator>> partition() const {\n";
1084 out <<
"std::vector<range<iterator>> res;\n";
1085 out <<
"for (const auto& cur : ind_" << masterIndex <<
".partition(10000)) {\n";
1086 out <<
" res.push_back(make_range(iterator(cur.begin()), iterator(cur.end())));\n";
1088 out <<
"return res;\n";
1092 out <<
"void purge() {\n";
1093 for (
size_t i = 0;
i < numIndexes;
i++) {
1094 out <<
"ind_" <<
i <<
".clear();\n";
1099 out <<
"iterator begin() const {\n";
1100 out <<
"return iterator_" << masterIndex <<
"(ind_" << masterIndex <<
".begin());\n";
1103 out <<
"iterator end() const {\n";
1104 out <<
"return iterator_" << masterIndex <<
"(ind_" << masterIndex <<
".end());\n";
1108 out <<
"void printStatistics(std::ostream& o) const {\n";
1109 for (
size_t i = 0;
i < numIndexes;
i++) {
1110 out <<
"o << \" arity " << arity <<
" brie index " <<
i <<
" lex-order " << inds[
i] <<
"\\n\";\n";
1112 out <<
"ind_" <<
i <<
".printStats(o);\n";
1117 for (
size_t i = 0;
i < numIndexes;
i++) {
1119 out <<
"static t_tuple orderIn_" <<
i <<
"(const t_tuple& t) {\n";
1120 out <<
"t_tuple res;\n";
1121 for (
size_t j = 0;
j < ind.size();
j++) {
1122 out <<
"res[" <<
j <<
"] = t[" << ind[
j] <<
"];\n";
1124 out <<
"return res;\n";
1127 out <<
"static t_tuple orderOut_" <<
i <<
"(const t_tuple& t) {\n";
1128 out <<
"t_tuple res;\n";
1129 for (
size_t j = 0;
j < ind.size();
j++) {
1130 out <<
"res[" << ind[
j] <<
"] = t[" <<
j <<
"];\n";
1132 out <<
"return res;\n";
1144 assert(!isProvenance &&
"eqrel cannot be used with provenance");
1148 computedIndices = {{0, 1}};
1159 const auto& inds = getIndices();
1160 size_t numIndexes = inds.size();
1161 std::map<MinIndexSelection::LexOrder, int> indexToNumMap;
1164 out <<
"struct " << getTypeName() <<
" {\n";
1165 out <<
"static constexpr Relation::arity_type Arity = " << arity <<
";\n";
1168 out <<
"using t_tuple = Tuple<RamDomain, " << arity <<
">;\n";
1169 out <<
"using t_ind_" << masterIndex <<
" = EquivalenceRelation<t_tuple>;\n";
1170 out <<
"t_ind_" << masterIndex <<
" ind_" << masterIndex <<
";\n";
1174 out <<
"class iterator_0 : public std::iterator<std::forward_iterator_tag, t_tuple> {\n";
1175 out <<
" using nested_iterator = typename t_ind_0::iterator;\n";
1176 out <<
" nested_iterator nested;\n";
1177 out <<
" t_tuple value;\n";
1180 out <<
" iterator_0() = default;\n";
1181 out <<
" iterator_0(const nested_iterator& iter) : nested(iter), value(orderOut_0(*iter)) {}\n";
1182 out <<
" iterator_0(const iterator_0& other) = default;\n";
1183 out <<
" iterator_0& operator=(const iterator_0& other) = default;\n";
1185 out <<
" bool operator==(const iterator_0& other) const {\n";
1186 out <<
" return nested == other.nested;\n";
1189 out <<
" bool operator!=(const iterator_0& other) const {\n";
1190 out <<
" return !(*this == other);\n";
1193 out <<
" const t_tuple& operator*() const {\n";
1194 out <<
" return value;\n";
1197 out <<
" const t_tuple* operator->() const {\n";
1198 out <<
" return &value;\n";
1201 out <<
" iterator_0& operator++() {\n";
1202 out <<
" ++nested;\n";
1203 out <<
" value = orderOut_0(*nested);\n";
1204 out <<
" return *this;\n";
1208 out <<
"using iterator = iterator_" << masterIndex <<
";\n";
1211 out <<
"struct context {\n";
1212 out <<
"t_ind_" << masterIndex <<
"::operation_hints hints_" << masterIndex <<
";\n";
1214 out <<
"context createContext() { return context(); }\n";
1217 out <<
"bool insert(const t_tuple& t) {\n";
1218 out <<
"return ind_" << masterIndex <<
".insert(t[0], t[1]);\n";
1221 out <<
"bool insert(const t_tuple& t, context& h) {\n";
1222 out <<
"return ind_" << masterIndex <<
".insert(t[0], t[1], h.hints_" << masterIndex <<
");\n";
1225 out <<
"bool insert(const RamDomain* ramDomain) {\n";
1226 out <<
"RamDomain data[2];\n";
1227 out <<
"std::copy(ramDomain, ramDomain + 2, data);\n";
1228 out <<
"const t_tuple& tuple = reinterpret_cast<const t_tuple&>(data);\n";
1229 out <<
"context h;\n";
1230 out <<
"return insert(tuple, h);\n";
1233 out <<
"bool insert(RamDomain a1, RamDomain a2) {\n";
1234 out <<
"RamDomain data[2] = {a1, a2};\n";
1235 out <<
"return insert(data);\n";
1241 out <<
"void extend(const " << getTypeName() <<
"& other) {\n";
1242 out <<
"ind_" << masterIndex <<
".extend(other.ind_" << masterIndex <<
");\n";
1246 out <<
"bool contains(const t_tuple& t) const {\n";
1247 out <<
"return ind_" << masterIndex <<
".contains(t[0], t[1]);\n";
1250 out <<
"bool contains(const t_tuple& t, context& h) const {\n";
1251 out <<
"return ind_" << masterIndex <<
".contains(t[0], t[1]);\n";
1255 out <<
"std::size_t size() const {\n";
1256 out <<
"return ind_" << masterIndex <<
".size();\n";
1260 out <<
"iterator find(const t_tuple& t) const {\n";
1261 out <<
"return ind_" << masterIndex <<
".find(orderIn_" << masterIndex <<
"(t));\n";
1264 out <<
"iterator find(const t_tuple& t, context& h) const {\n";
1265 out <<
"return ind_" << masterIndex <<
".find(orderIn_" << masterIndex <<
"(t));\n";
1269 for (
int i = 1;
i < 4;
i++) {
1272 for (
size_t j = 0;
j < arity;
j++) {
1274 s[
j] = analysis::AttributeConstraint::Equal;
1278 out <<
"range<iterator> lowerUpperRange_" << s;
1279 out <<
"(const t_tuple& lower, const t_tuple& upper, context& h) const {\n";
1282 for (
size_t column = 0; column < 2; column++) {
1283 if (((
i >> column) & 1) != 0) {
1287 out <<
"auto r = ind_" << masterIndex <<
".template getBoundaries<" << indSize <<
">(orderIn_"
1288 << masterIndex <<
"(lower), h.hints_" << masterIndex <<
");\n";
1289 out <<
"return make_range(iterator(r.begin()), iterator(r.end()));\n";
1292 out <<
"range<iterator> lowerUpperRange_" << s;
1293 out <<
"(const t_tuple& lower, const t_tuple& upper) const {\n";
1294 out <<
"context h; return lowerUpperRange_" << s <<
"(lower, upper, h);\n";
1299 out <<
"bool empty() const {\n";
1300 out <<
"return ind_" << masterIndex <<
".size() == 0;\n";
1304 out <<
"std::vector<range<iterator>> partition() const {\n";
1305 out <<
"std::vector<range<iterator>> res;\n";
1306 out <<
"for (const auto& cur : ind_" << masterIndex <<
".partition(10000)) {\n";
1307 out <<
" res.push_back(make_range(iterator(cur.begin()), iterator(cur.end())));\n";
1309 out <<
"return res;\n";
1313 out <<
"void purge() {\n";
1314 for (
size_t i = 0;
i < numIndexes;
i++) {
1315 out <<
"ind_" <<
i <<
".clear();\n";
1320 out <<
"iterator begin() const {\n";
1321 out <<
"return iterator_" << masterIndex <<
"(ind_" << masterIndex <<
".begin());\n";
1324 out <<
"iterator end() const {\n";
1325 out <<
"return iterator_" << masterIndex <<
"(ind_" << masterIndex <<
".end());\n";
1329 out <<
"void printStatistics(std::ostream& o) const {\n";
1330 out <<
"o << \" eqrel index: no hint statistics supported\\n\";\n";
1335 for (
size_t i = 0;
i < numIndexes;
i++) {
1337 out <<
"static t_tuple orderIn_" <<
i <<
"(const t_tuple& t) {\n";
1338 out <<
"t_tuple res;\n";
1339 for (
size_t j = 0;
j < ind.size();
j++) {
1340 out <<
"res[" <<
j <<
"] = t[" << ind[
j] <<
"];\n";
1342 out <<
"return res;\n";
1345 out <<
"static t_tuple orderOut_" <<
i <<
"(const t_tuple& t) {\n";
1346 out <<
"t_tuple res;\n";
1347 for (
size_t j = 0;
j < ind.size();
j++) {
1348 out <<
"res[" << ind[
j] <<
"] = t[" <<
j <<
"];\n";
1350 out <<
"return res;\n";