TupleIterator *Reasoner::getMagicIterator(Literal &query, std::vector<uint8_t> *posJoins, std::vector<Term_t> *possibleValuesJoins, EDBLayer &edb, Program &program, bool returnOnlyVars) { BOOST_LOG_TRIVIAL(debug) << "Get magic iterator for pattern " << query.tostring(&program, &edb); /*//Transfor pattern in query VTuple t(3); int nvars = 0;*/ //To use if the flag returnOnlyVars is set to false uint64_t outputTuple[3]; // Used in trident method, so no Term_t uint8_t nPosToCopy = 0; uint8_t posToCopy[3]; std::vector<uint8_t> newPosJoins; //This is used because I need the posJoins in the original triple, and not on the variables if (posJoins != NULL) { newPosJoins = *posJoins; for (int j = 0; j < query.getTupleSize(); ++j) { if (!query.getTermAtPos(j).isVariable()) { //Increment all newPosToJoin for (int m = 0; m < newPosJoins.size(); ++m) { if (newPosJoins[m] >= j) newPosJoins[m]++; } } else { posToCopy[nPosToCopy++] = j; } } } /*if (pattern->subject() < 0) { //Variable uint8_t id = (uint8_t)program.getIDVar(pattern->getVar(nvars++)); t.set(VTerm(id, 0), 0); posToCopy[nPosToCopy++] = 0; } else { //Constant t.set(VTerm(0, pattern->subject()), 0); outputTuple[0] = pattern->subject(); if (newPosJoins.size() == 2) { newPosJoins[0]++; newPosJoins[1]++; } if (newPosJoins.size() == 1) { newPosJoins[0]++; } } if (pattern->predicate() < 0) { //Variable uint8_t id = (uint8_t)program.getIDVar(pattern->getVar(nvars++)); t.set(VTerm(id, 0), 1); posToCopy[nPosToCopy++] = 1; } else { //Constant t.set(VTerm(0, pattern->predicate()), 1); outputTuple[1] = pattern->predicate(); if (newPosJoins.size() == 1 && newPosJoins[0] == 1) { newPosJoins[0]++; } if (newPosJoins.size() == 2 && newPosJoins[1] == 1) { newPosJoins[1]++; } } if (pattern->object() < 0) { //Variable uint8_t id = (uint8_t)program.getIDVar(pattern->getVar(nvars++)); t.set(VTerm(id, 0), 2); posToCopy[nPosToCopy++] = 2; } else { //Constant t.set(VTerm(0, pattern->object()), 2); outputTuple[2] = pattern->object(); }*/ //Replace variables with constants if posJoins != NULL. VTuple t = query.getTuple(); VTuple boundTuple = t; if (posJoins != NULL) { //The posjoins do not include constants int j = 0; for (std::vector<uint8_t>::const_iterator itr = newPosJoins.begin(); itr != newPosJoins.end(); ++itr) { boundTuple.set(VTerm(0, possibleValuesJoins->at(j++)), *itr); } } /*std::string ti("TI"); Literal query(program.getPredicate(ti, Predicate::calculateAdornment(boundTuple)), boundTuple);*/ //Get all adorned rules Wizard wizard; std::shared_ptr<Program> adornedProgram = wizard.getAdornedProgram(query, program); //Rewrite and add the rules std::pair<PredId_t, PredId_t> inputOutputRelIDs; std::shared_ptr<Program> magicProgram = wizard.doMagic(query, adornedProgram, inputOutputRelIDs); #ifdef DEBUG //Print all rules BOOST_LOG_TRIVIAL(debug) << "Rewritten program:"; std::vector<Rule> newRules = magicProgram->getAllRules(); for (std::vector<Rule>::iterator itr = newRules.begin(); itr != newRules.end(); ++itr) { BOOST_LOG_TRIVIAL(debug) << itr->tostring(magicProgram.get(), &edb); } #endif SemiNaiver naiver(magicProgram->getAllRules(), edb, magicProgram.get(), true, true) ; //Add all the input tuples in the input relation Predicate pred = magicProgram->getPredicate(inputOutputRelIDs.first); VTuple onlyConstsTuple(pred.getCardinality()); int j = 0; for (int i = 0; i < t.getSize(); ++i) { if (!boundTuple.get(i).isVariable()) { onlyConstsTuple.set(VTerm(0, t.get(i).getValue()), j++); } } Literal unboundQuery(pred, onlyConstsTuple); naiver.addDataToIDBRelation(magicProgram->getPredicate(inputOutputRelIDs.first), getBlockFromQuery(unboundQuery, query, newPosJoins.size() != 0 ? &newPosJoins : NULL, possibleValuesJoins)); //Exec the materialization naiver.run(1, 2); //Extract the tuples from the output relation Literal outputLiteral(magicProgram->getPredicate(inputOutputRelIDs.second), t); FCIterator itr = naiver.getTable(outputLiteral, 0, (size_t) - 1); TupleTable *finalTable; if (returnOnlyVars) { finalTable = new TupleTable(outputLiteral.getNVars()); } else { finalTable = new TupleTable(3); } while (!itr.isEmpty()) { std::shared_ptr<const FCInternalTable> table = itr.getCurrentTable(); FCInternalTableItr *itrTable = table->getIterator(); if (returnOnlyVars) { const uint8_t rowSize = table->getRowSize(); while (itrTable->hasNext()) { itrTable->next(); for (uint8_t j = 0; j < rowSize; ++j) { finalTable->addValue(itrTable->getCurrentValue(j)); } } } else { while (itrTable->hasNext()) { itrTable->next(); for (uint8_t j = 0; j < nPosToCopy; ++j) { outputTuple[posToCopy[j]] = itrTable->getCurrentValue(j); } finalTable->addRow(outputTuple); } } table->releaseIterator(itrTable); itr.moveNextCount(); } std::shared_ptr<TupleTable> pFinalTable(finalTable); return new TupleTableItr(pFinalTable); }