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