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); }
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; }