예제 #1
0
void Database::processRule(Rule* rule) {
    //Find the relation in the list of schemes matching the head of the predicate
    Relation* headRelation = getHeadRelation(rule);
    
    //Get the list of predicates
    std::vector<Predicate*> predicateList = rule->j;
    
    //Create new relations from each predicate
    std::vector<Relation*> relationList = getRelationList(predicateList);
    
    //Natural join the relations from the predicates
    Relation* newRelation = join(relationList);
    
    //Project on the final relation; only keep columns matching variables in the rule head
    std::vector<std::string> headVariables = getHeadVariables(rule->hpl);
    newRelation = newRelation->project(headVariables);
    
    //Find the relation in the database that matches the head of the rule
        //Already done (it's headRelation)
    
    //Rename attributes in the new relation so it matches the rule head's schema
    newRelation = renameToMatch(headRelation, newRelation, headVariables);
    
    //Union the new relation with the matching relation
    headRelation = unionWith(headRelation, newRelation);
    std::sort(headRelation->facts.begin(), headRelation->facts.end(), Relation::tupleCompare);
}
예제 #2
0
bool RecursiveClauses::computeIsRecursive(const AstClause& clause, const AstTranslationUnit& translationUnit) const {
    const AstProgram &program = *translationUnit.getProgram();

    // we want to reach the atom of the head through the body
    const AstRelation* trg = getHeadRelation(&clause, &program);

    std::set<const AstRelation*> reached;
    std::vector<const AstRelation*> worklist;

    // set up start list
    for(const AstAtom* cur : clause.getAtoms()) {
        auto rel = program.getRelation(cur->getName());
        if (rel == trg) return true;
        worklist.push_back(rel);
    }

    // process remaining elements
    while(!worklist.empty()) {
        // get next to process
        const AstRelation* cur = worklist.back();
        worklist.pop_back();

        // skip null pointers (errors in the input code)
        if (!cur) continue;

        // check whether this one has been checked before
        if (!reached.insert(cur).second) continue;

        // check all atoms in the relations
        for(const AstClause* cl : cur->getClauses()) {
            for(const AstAtom* at : cl->getAtoms()) {
                auto rel = program.getRelation(at->getName());
                if (rel == trg) return true;
                worklist.push_back(rel);
            }
        }
    }

    // no cycles found
    return false;

}