public static List<AttributeRef> findTargetQueriedAttributesForExtTGD(Dependency dependency) {
   List<AttributeRef> queriedAttributes = new ArrayList<AttributeRef>();
   LunaticUtility.addAllIfNotContained(
       queriedAttributes, findTargetQueriedAttributesInPremise(dependency));
   for (FormulaVariable formulaVariable : dependency.getPremise().getLocalVariables()) {
     if (formulaVariable.getConclusionRelationalOccurrences().isEmpty()) {
       continue;
     }
     AttributeRef firstPremiseOccurrenceInTarget =
         getFirstPremiseOccurrenceInTarget(formulaVariable.getPremiseRelationalOccurrences());
     if (firstPremiseOccurrenceInTarget != null) {
       AttributeRef unaliasedPremiseAttribute =
           ChaseUtility.unAlias(firstPremiseOccurrenceInTarget);
       LunaticUtility.addIfNotContained(queriedAttributes, unaliasedPremiseAttribute);
     }
     for (FormulaVariableOccurrence conclusionOccurrence :
         formulaVariable.getConclusionRelationalOccurrences()) {
       AttributeRef attribute = conclusionOccurrence.getAttributeRef();
       if (attribute.getTableAlias().isSource()) {
         continue;
       }
       AttributeRef unaliasedConclusionAttribute =
           ChaseUtility.unAlias(conclusionOccurrence.getAttributeRef());
       LunaticUtility.addIfNotContained(queriedAttributes, unaliasedConclusionAttribute);
     }
   }
   return queriedAttributes;
 }
 private boolean purgeOverlappingContexts(
     Dependency egd, Repair repair, Set<AttributeRef> affectedAttributesSoFar) {
   // Needed also for FDs due to the presence of cellgroups that can span different eq. classes,
   //  but only if some earlier dependencies has generated a cell group for this attribute
   if (affectedAttributesSoFar.isEmpty()) {
     return true;
   }
   if (logger.isDebugEnabled())
     logger.debug("Checking independence of violation contexts for egd " + egd);
   boolean consistent = true;
   Map<AttributeRef, Set<CellRef>> changedCellMap = new HashMap<AttributeRef, Set<CellRef>>();
   for (Iterator<ChangeDescription> it = repair.getChangeDescriptions().iterator();
       it.hasNext(); ) {
     ChangeDescription changeDescription = it.next();
     Set<AttributeRef> changedAttributes =
         ChaseUtility.extractAffectedAttributes(changeDescription);
     if (LunaticUtility.hasEmptyIntersection(affectedAttributesSoFar, changedAttributes)) {
       continue;
     }
     if (ChaseUtility.occurrencesOverlap(changeDescription, changedCellMap)
         || ChaseUtility.witnessOverlaps(changeDescription, changedCellMap)) {
       if (logger.isDebugEnabled())
         logger.debug("Violation context has overlaps: " + changeDescription);
       it.remove();
       consistent = false;
     } else {
       ChaseUtility.addChangedCellsToMap(
           changeDescription.getCellGroup().getOccurrences(), changedCellMap);
     }
   }
   return consistent;
 }
 private void addAdditionalAttributes(
     CellGroup cellGroup, TupleOID originalOIDForConclusionValue, Tuple tuple, Dependency egd) {
   for (AttributeRef additionalAttribute : egd.getAdditionalAttributes()) {
     for (Cell additionalCell : tuple.getCells()) {
       AttributeRef unaliasedAttribute = ChaseUtility.unAlias(additionalCell.getAttributeRef());
       if (!unaliasedAttribute.equals(additionalAttribute)) {
         continue;
       }
       TupleOID originalOIDForCell =
           new TupleOID(ChaseUtility.getOriginalOid(tuple, additionalCell.getAttributeRef()));
       if (!originalOIDForCell.equals(originalOIDForConclusionValue)) {
         continue;
       }
       CellGroupCell additionalCellGroupCell =
           new CellGroupCell(
               originalOIDForCell,
               unaliasedAttribute,
               additionalCell.getValue(),
               null,
               LunaticConstants.TYPE_ADDITIONAL,
               null);
       cellGroup.addAdditionalCell(additionalAttribute, additionalCellGroupCell);
     }
   }
 }
 private void addTuple(
     Tuple tuple,
     EquivalenceClassForSymmetricEGD equivalenceClass,
     CostManagerConfiguration costManagerConfiguration,
     IDatabase deltaDB,
     String stepId,
     Scenario scenario) {
   if (logger.isDebugEnabled())
     logger.trace("Adding tuple " + tuple + " to equivalence class: " + equivalenceClass);
   AttributeRef conclusionAttribute = equivalenceClass.getConclusionAttribute();
   Cell cellToChangeForForwardChasing = tuple.getCell(conclusionAttribute);
   if (logger.isDebugEnabled())
     logger.trace(
         "Attribute: " + conclusionAttribute + " - Cell: " + cellToChangeForForwardChasing);
   IValue conclusionValue = cellToChangeForForwardChasing.getValue();
   TupleOID originalOid = new TupleOID(ChaseUtility.getOriginalOid(tuple, conclusionAttribute));
   CellRef cellRef = new CellRef(originalOid, ChaseUtility.unAlias(conclusionAttribute));
   CellGroupCell targetCell =
       new CellGroupCell(cellRef, conclusionValue, null, LunaticConstants.TYPE_OCCURRENCE, null);
   CellGroup forwardCellGroup = new CellGroup(conclusionValue, true);
   forwardCellGroup.addOccurrenceCell(targetCell);
   addAdditionalAttributes(forwardCellGroup, originalOid, tuple, equivalenceClass.getEGD());
   CellGroup enrichedCellGroup =
       this.occurrenceHandler.enrichCellGroups(forwardCellGroup, deltaDB, stepId, scenario);
   EGDEquivalenceClassTuple tupleCells = new EGDEquivalenceClassTuple(enrichedCellGroup);
   for (BackwardAttribute backwardAttribute :
       equivalenceClass.getAttributesToChangeForBackwardChasing()) {
     AttributeRef attributeForBackwardChasing = backwardAttribute.getAttributeRef();
     Cell cellForBackward = tuple.getCell(attributeForBackwardChasing);
     TupleOID tupleOid =
         new TupleOID(ChaseUtility.getOriginalOid(tuple, attributeForBackwardChasing));
     Cell backwardCell =
         new Cell(
             tupleOid,
             ChaseUtility.unAlias(attributeForBackwardChasing),
             cellForBackward.getValue());
     IValue value = backwardCell.getValue();
     CellGroup backwardCellGroup = new CellGroup(value, true);
     backwardCellGroup.addOccurrenceCell(
         new CellGroupCell(backwardCell, null, LunaticConstants.TYPE_OCCURRENCE, null));
     CellGroup enrichedBackwardCellGroup =
         this.occurrenceHandler.enrichCellGroups(backwardCellGroup, deltaDB, stepId, scenario);
     tupleCells.setCellGroupForBackwardAttribute(backwardAttribute, enrichedBackwardCellGroup);
   }
   equivalenceClass.addTupleCells(tupleCells);
   equivalenceClass.addTupleCellsForValue(conclusionValue, tupleCells);
   if (costManagerConfiguration.isDoBackwardOnDependency(equivalenceClass.getEGD())) {
     indexCells(tupleCells, equivalenceClass);
   }
   if (logger.isDebugEnabled()) logger.trace("Equivalence class: " + equivalenceClass);
 }
 public static List<AttributeRef> findTargetJoinAttributesInPositiveFormula(
     Dependency dependency) {
   List<VariableEquivalenceClass> relevantVariableClasses =
       ChaseUtility.findJoinVariablesInTarget(dependency);
   List<AttributeRef> targetJoinAttributes = new ArrayList<AttributeRef>();
   for (VariableEquivalenceClass variableEquivalenceClass : relevantVariableClasses) {
     List<FormulaVariableOccurrence> targetOccurrencesForEquivalenceClass =
         ChaseUtility.findTargetOccurrences(variableEquivalenceClass);
     List<FormulaVariableOccurrence> positiveTargetOccurrencesForEquivalenceClass =
         ChaseUtility.findPositiveOccurrences(
             dependency.getPremise().getPositiveFormula(), targetOccurrencesForEquivalenceClass);
     for (FormulaVariableOccurrence occurrence : positiveTargetOccurrencesForEquivalenceClass) {
       targetJoinAttributes.add(occurrence.getAttributeRef());
     }
   }
   return targetJoinAttributes;
 }
 private NewChaseSteps applyRepairs(
     DeltaChaseStep currentNode, List<Repair> repairs, Dependency egd, Scenario scenario) {
   if (logger.isDebugEnabled()) logger.debug("---Applying repairs...");
   NewChaseSteps newChaseSteps = new NewChaseSteps(egd);
   for (int i = 0; i < repairs.size(); i++) {
     Repair repair = repairs.get(i);
     boolean consistentRepair =
         purgeOverlappingContexts(egd, repair, currentNode.getAffectedAttributesInAncestors());
     try {
       CellGroupUtility.checkCellGroupConsistency(repair);
     } catch (ChaseException ex) { // TODO++
       IExportSolution solutionExporter =
           OperatorFactory.getInstance().getSolutionExporter(scenario);
       solutionExporter.export(currentNode, "error", scenario);
       throw ex;
     }
     String egdId = egd.getId();
     String localId = ChaseUtility.generateChaseStepIdForEGDs(egdId, i, repair);
     DeltaChaseStep newStep =
         new DeltaChaseStep(scenario, currentNode, localId, egd, repair, repair.getChaseModes());
     for (ChangeDescription changeSet : repair.getChangeDescriptions()) {
       this.cellChanger.changeCells(
           changeSet.getCellGroup(), newStep.getDeltaDB(), newStep.getId(), scenario);
     }
     if (consistentRepair) {
       if (logger.isDebugEnabled())
         logger.debug("EGD " + egd.getId() + " is satisfied in this step...");
       newStep.addSatisfiedEGD(egd);
     }
     newStep.setAffectedAttributesInNode(ChaseUtility.extractAffectedAttributes(repair));
     newStep.setAffectedAttributesInAncestors(
         ChaseUtility.findChangedAttributesInAncestors(newStep));
     if (logger.isDebugEnabled())
       logger.debug("Generated step " + newStep.getId() + " for repair: " + repair);
     newChaseSteps.addChaseStep(newStep);
   }
   this.cellChanger.flush(currentNode.getDeltaDB());
   if (repairs.isEmpty()) {
     newChaseSteps.setNoRepairsNeeded(true);
   }
   return newChaseSteps;
 }
 public static List<AttributeRef> findTargetQueriedAttributesInPremise(Dependency dependency) {
   if (logger.isTraceEnabled())
     logger.trace("Searching query attributes for dependency: \n" + dependency);
   List<AttributeRef> queriedAttributes = new ArrayList<AttributeRef>();
   for (FormulaVariable variable : dependency.getPremise().getLocalVariables()) {
     if (logger.isTraceEnabled()) logger.trace("Inspecting variable: " + variable);
     if (hasSingleOccurrenceInPremise(variable)) {
       continue;
     }
     for (FormulaVariableOccurrence occurrence : variable.getPremiseRelationalOccurrences()) {
       if (logger.isTraceEnabled()) logger.trace("Inspecting occurrence: " + occurrence);
       AttributeRef attribute = occurrence.getAttributeRef();
       if (attribute.getTableAlias().isSource()) {
         continue;
       }
       AttributeRef unaliasedAttribute = ChaseUtility.unAlias(attribute);
       LunaticUtility.addIfNotContained(queriedAttributes, unaliasedAttribute);
     }
   }
   if (logger.isTraceEnabled()) logger.trace("Result: " + queriedAttributes);
   return queriedAttributes;
 }
 public static List<AttributeRef> extractRequestedAttributesWithExistential(
     Dependency dependency) {
   List<AttributeRef> result = new ArrayList<AttributeRef>();
   result.addAll(dependency.getQueriedAttributes());
   for (FormulaVariable variable : dependency.getConclusion().getLocalVariables()) {
     if (variable.getConclusionRelationalOccurrences().size() == 1) {
       continue;
     }
     for (FormulaVariableOccurrence occurrence : variable.getConclusionRelationalOccurrences()) {
       if (logger.isTraceEnabled()) logger.trace("Inspecting occurrence: " + occurrence);
       AttributeRef attribute = occurrence.getAttributeRef();
       AttributeRef unaliasedAttribute = ChaseUtility.unAlias(attribute);
       LunaticUtility.addIfNotContained(result, unaliasedAttribute);
     }
   }
   for (AttributeRef attributeRef : dependency.getAdditionalAttributes()) {
     if (!result.contains(attributeRef)) {
       result.add(attributeRef);
     }
   }
   return result;
 }
 @Override
 public NewChaseSteps chaseDependency(
     DeltaChaseStep currentNode,
     Dependency egd,
     IAlgebraOperator premiseQuery,
     Scenario scenario,
     IChaseState chaseState,
     IDatabase databaseForStep) {
   if (logger.isDebugEnabled())
     logger.debug("***** Step: " + currentNode.getId() + " - Chasing dependency: " + egd);
   if (logger.isTraceEnabled()) logger.trace(databaseForStep.printInstances());
   this.lastTuple = null;
   this.lastTupleHandled = false;
   if (logger.isDebugEnabled()) logger.debug("Executing premise query: " + premiseQuery);
   if (logger.isTraceEnabled())
     logger.debug(
         "Result:\n"
             + LunaticUtility.printIterator(
                 queryRunner.run(premiseQuery, scenario.getSource(), databaseForStep)));
   long violationQueryStart = new Date().getTime();
   ITupleIterator it = queryRunner.run(premiseQuery, scenario.getSource(), databaseForStep);
   long violationQueryEnd = new Date().getTime();
   ChaseStats.getInstance()
       .addStat(ChaseStats.EGD_VIOLATION_QUERY_TIME, violationQueryEnd - violationQueryStart);
   List<Repair> repairsForDependency = new ArrayList<Repair>();
   try {
     while (true) {
       long equivalenceClassStart = new Date().getTime();
       EquivalenceClassForSymmetricEGD equivalenceClass =
           readNextEquivalenceClass(
               it, egd, currentNode.getDeltaDB(), currentNode.getId(), chaseState, scenario);
       long equivalenceClassEnd = new Date().getTime();
       ChaseStats.getInstance()
           .addStat(
               ChaseStats.EGD_EQUIVALENCE_CLASS_TIME, equivalenceClassEnd - equivalenceClassStart);
       if (equivalenceClass == null) {
         break;
       }
       ICostManager costManager = CostManagerFactory.getCostManager(egd, scenario);
       long choosingRepairStart = new Date().getTime();
       List<Repair> repairsForEquivalenceClass =
           costManager.chooseRepairStrategy(
               new EquivalenceClassForEGDProxy(equivalenceClass),
               currentNode.getRoot(),
               repairsForDependency,
               scenario,
               currentNode.getId(),
               occurrenceHandler);
       long choosingRepairEnd = new Date().getTime();
       ChaseStats.getInstance()
           .addStat(ChaseStats.EGD_CHOOSING_REPAIR_TIME, choosingRepairEnd - choosingRepairStart);
       if (logger.isDebugEnabled())
         logger.debug(
             "Repairs for equivalence class: "
                 + LunaticUtility.printCollection(repairsForEquivalenceClass));
       repairsForDependency =
           ChaseUtility.accumulateRepairs(repairsForDependency, repairsForEquivalenceClass);
       if (noMoreTuples(it)) {
         break;
       }
       if (logger.isDebugEnabled())
         logger.debug("Repairs for equivalence classes so far: " + repairsForDependency.size());
     }
   } catch (ChaseFailedException e) {
     throw e;
   } finally {
     it.close();
   }
   if (logger.isDebugEnabled())
     logger.debug(
         "Total repairs for dependency: " + LunaticUtility.printCollection(repairsForDependency));
   long repairStart = new Date().getTime();
   NewChaseSteps newSteps = applyRepairs(currentNode, repairsForDependency, egd, scenario);
   long repairEnd = new Date().getTime();
   ChaseStats.getInstance().addStat(ChaseStats.EGD_REPAIR_TIME, repairEnd - repairStart);
   return newSteps;
 }
 private EquivalenceClassForSymmetricEGD readNextEquivalenceClass(
     ITupleIterator it,
     Dependency egd,
     IDatabase deltaDB,
     String stepId,
     IChaseState chaseState,
     Scenario scenario) {
   if (!it.hasNext() && (this.lastTupleHandled || this.lastTuple == null)) {
     return null;
   }
   EquivalenceClassForSymmetricEGD equivalenceClass = createEquivalenceClass(egd);
   if (lastTuple != null && !this.lastTupleHandled) {
     if (logger.isDebugEnabled())
       logger.debug("Reading tuple : " + this.lastTuple.toStringWithOIDAndAlias());
     addTuple(
         this.lastTuple,
         equivalenceClass,
         scenario.getCostManagerConfiguration(),
         deltaDB,
         stepId,
         scenario);
     this.lastTupleHandled = true;
   }
   if (logger.isDebugEnabled()) logger.debug("Reading next equivalence class...");
   while (it.hasNext()) {
     if (chaseState.isCancelled())
       ChaseUtility.stopChase(
           chaseState); // throw new ChaseException("Chase interrupted by user");
     Tuple tuple = it.next();
     if (logger.isDebugEnabled())
       logger.debug("Reading tuple : " + tuple.toStringWithOIDAndAlias());
     if (lastTuple == null
         || equivalenceClass.isEmpty()
         || EquivalenceClassUtility.sameEquivalenceClass(tuple, this.lastTuple, egd)) {
       addTuple(
           tuple,
           equivalenceClass,
           scenario.getCostManagerConfiguration(),
           deltaDB,
           stepId,
           scenario);
       this.lastTuple = tuple;
       this.lastTupleHandled = true;
     } else {
       if (logger.isDebugEnabled()) logger.debug("Equivalence class is finished...");
       if (equivalenceClass.isEmpty()) {
         throw new IllegalArgumentException(
             "Unable to create equivalence class for egd:\n"
                 + egd
                 + "\nLast tuple: \n"
                 + lastTuple
                 + "\nCurrent tuple: \n"
                 + tuple);
       }
       this.lastTuple = tuple;
       this.lastTupleHandled = false;
       break;
     }
   }
   if (logger.isDebugEnabled()) logger.debug("Equivalence class loaded");
   if (logger.isDebugEnabled())
     logger.debug("-------- Equivalence class:\n" + equivalenceClass + "\n---------------");
   return equivalenceClass;
 }