Exemplo n.º 1
0
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);
}