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