/// <summary> /// Copy Constructor /// </summary> internal Cell(Cell source) { m_cQuery = new CellQuery(source.m_cQuery); m_sQuery = new CellQuery(source.m_sQuery); m_label = new CellLabel(source.m_label); m_cellNumber = source.m_cellNumber; }
// effects: Creates a view cell relation for "cell" with the // projected slots given by slots -- cellNumber is the number of the // cell for debugging purposes // Also creates the BasicCellRelations for the left and right cell queries internal ViewCellRelation(Cell cell, List<ViewCellSlot> slots, int cellNumber) : base(cellNumber) { m_cell = cell; m_slots = slots; // We create the basiccellrelations passing this to it so that we have // a reference from the basiccellrelations to this m_cell.CQuery.CreateBasicCellRelation(this); m_cell.SQuery.CreateBasicCellRelation(this); }
private static List<List<int>> GetSlotNumsForColumns(Cell cell, IEnumerable<MemberPath> columns) { var slotNums = new List<List<int>>(); var set = cell.CQuery.Extent as AssociationSet; //If it is an association set, the columns could be projected //in either end so get the slotNums from both the ends if (set != null) { foreach (var setEnd in set.AssociationSetEnds) { var endSlots = cell.CQuery.GetAssociationEndSlots(setEnd.CorrespondingAssociationEndMember); Debug.Assert(endSlots.Count > 0); var localslotNums = cell.SQuery.GetProjectedPositions(columns, endSlots); if (localslotNums != null) { slotNums.Add(localslotNums); } } } else { var localslotNums = cell.SQuery.GetProjectedPositions(columns); if (localslotNums != null) { slotNums.Add(localslotNums); } } return slotNums; }
// effects: Returns the end to which columns are exactly mapped in the // relationship set given by cell.CQuery.Extent -- if this extent is // an entityset returns null. If the columns are not mapped in this cell to an // end exactly or columns are not projected in cell, returns null private static AssociationEndMember GetRelationEndForColumns(Cell cell, IEnumerable<MemberPath> columns) { if (cell.CQuery.Extent is EntitySet) { return null; } var relationSet = (AssociationSet)cell.CQuery.Extent; // Go through all the ends and see if they are mapped in this cell foreach (var relationEnd in relationSet.AssociationSetEnds) { var endMember = relationEnd.CorrespondingAssociationEndMember; var prefix = new MemberPath(relationSet, endMember); // Note: primaryKey is the key for the entity set but // prefixed with the relationship's path - we are trying to // check if the entity's keys are mapped in this cell as an end var primaryKey = ExtentKey.GetPrimaryKeyForEntityType(prefix, relationEnd.EntitySet.ElementType); // Check if this end is mapped in this cell -- we are // checking on the C-side -- we get all the indexes of the // end's keyfields var endIndexes = cell.CQuery.GetProjectedPositions(primaryKey.KeyFields); if (endIndexes != null) { // Get all the slots corresponding to the columns // But stick to the slots with in these ends since the same column might be //projected twice in different ends var columnIndexes = cell.SQuery.GetProjectedPositions(columns, endIndexes); if (columnIndexes == null) { continue; // columns are not projected with in this end } // Note that the positions need not match exactly - we have a // separate test that will do that for us: CheckForeignKeyColumnOrder if (Helpers.IsSetEqual(columnIndexes, endIndexes, EqualityComparer<int>.Default)) { // The columns map exactly to this end -- return it return endMember; } } } return null; }
// effects: Given the foreign key constraint, checks if the // constraint.ParentColumns are mapped to the entity set E'e keys in // C-space where E corresponds to the entity set corresponding to end // Returns true iff such a mapping exists in cell private bool CheckParentColumnsForForeignKey( Cell cell, IEnumerable<Cell> cells, AssociationEndMember parentEnd, ref List<ErrorLog.Record> errorList) { // The child columns are mapped to some end of cell.CQuery.Extent. ParentColumns // must correspond to the EntitySet for this end var relationSet = (AssociationSet)cell.CQuery.Extent; var endSet = MetadataHelper.GetEntitySetAtEnd(relationSet, parentEnd); // Check if the ParentColumns are mapped to endSet's keys // Find the entity set that they map to - if any var entitySet = FindEntitySetForColumnsMappedToEntityKeys(cells, ParentColumns); if (entitySet == null || endSet.Equals(entitySet) == false) { if (errorList == null) //lazily initialize only if there is an error { errorList = new List<ErrorLog.Record>(); } // childColumns are mapped to parentEnd but ParentColumns are not mapped to the end // corresponding to the parentEnd -- this is an error var message = Strings.ViewGen_Foreign_Key_ParentTable_NotMappedToEnd( ToUserString(), ChildTable.Name, cell.CQuery.Extent.Name, parentEnd.Name, ParentTable.Name, endSet.Name); var record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyParentTableNotMappedToEnd, message, cell, String.Empty); errorList.Add(record); return false; } return true; }
// requires: IsForeignKeySuperSetOfPrimaryKeyInChildTable() is false // effects: Given that both the ChildColumns in this and the // primaryKey of ChildTable are mapped. Return true iff no error occurred private bool CheckConstraintWhenParentChildMapped( Cell cell, ErrorLog errorLog, AssociationEndMember parentEnd, ConfigViewGenerator config) { var ok = true; // The foreign key constraint has been mapped to a // relationship. Check if the multiplicities are consistent // If all columns in the child table (corresponding to // the constraint) are nullable, the parent end can be // 0..1 or 1..1. Else if must be 1..1 if (parentEnd.RelationshipMultiplicity == RelationshipMultiplicity.Many) { // Parent should at most one since we are talking // about foreign keys here var message = Strings.ViewGen_Foreign_Key_UpperBound_MustBeOne( ToUserString(), cell.CQuery.Extent.Name, parentEnd.Name); var record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyUpperBoundMustBeOne, message, cell, String.Empty); errorLog.AddEntry(record); ok = false; } if (MemberPath.AreAllMembersNullable(ChildColumns) == false && parentEnd.RelationshipMultiplicity != RelationshipMultiplicity.One) { // Some column in the constraint in the child table // is non-nullable and lower bound is not 1 var message = Strings.ViewGen_Foreign_Key_LowerBound_MustBeOne( ToUserString(), cell.CQuery.Extent.Name, parentEnd.Name); var record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyLowerBoundMustBeOne, message, cell, String.Empty); errorLog.AddEntry(record); ok = false; } if (config.IsNormalTracing && ok) { Trace.WriteLine("Foreign key mapped to relationship " + cell.CQuery.Extent.Name); } return ok; }
// effects: Returns an error record if the keys of the extent/associationSet being mapped are // present in the projected slots of this query. Returns null // otherwise. ownerCell indicates the cell that owns this and // resourceString is a resource used for error messages internal ErrorLog.Record VerifyKeysPresent( Cell ownerCell, Func<object, object, string> formatEntitySetMessage, Func<object, object, object, string> formatAssociationSetMessage, ViewGenErrorCode errorCode) { var prefixes = new List<MemberPath>(1); // Keep track of the key corresponding to each prefix var keys = new List<ExtentKey>(1); if (Extent is EntitySet) { // For entity set just get the full path of the key properties var prefix = new MemberPath(Extent); prefixes.Add(prefix); var entityType = (EntityType)Extent.ElementType; var entitySetKeys = ExtentKey.GetKeysForEntityType(prefix, entityType); Debug.Assert(entitySetKeys.Count == 1, "Currently, we only support primary keys"); keys.Add(entitySetKeys[0]); } else { var relationshipSet = (AssociationSet)Extent; // For association set, get the full path of the key // properties of each end foreach (var relationEnd in relationshipSet.AssociationSetEnds) { var assocEndMember = relationEnd.CorrespondingAssociationEndMember; var prefix = new MemberPath(relationshipSet, assocEndMember); prefixes.Add(prefix); var endKeys = ExtentKey.GetKeysForEntityType( prefix, MetadataHelper.GetEntityTypeForEnd(assocEndMember)); Debug.Assert(endKeys.Count == 1, "Currently, we only support primary keys"); keys.Add(endKeys[0]); } } for (var i = 0; i < prefixes.Count; i++) { var prefix = prefixes[i]; // Get all or none key slots that are being projected in this cell query var keySlots = MemberProjectedSlot.GetKeySlots(GetMemberProjectedSlots(), prefix); if (keySlots == null) { var key = keys[i]; string message; if (Extent is EntitySet) { var keyPropertiesString = MemberPath.PropertiesToUserString(key.KeyFields, true); message = formatEntitySetMessage(keyPropertiesString, Extent.Name); } else { var endName = prefix.RootEdmMember.Name; var keyPropertiesString = MemberPath.PropertiesToUserString(key.KeyFields, false); message = formatAssociationSetMessage(keyPropertiesString, endName, Extent.Name); } var error = new ErrorLog.Record(errorCode, message, ownerCell, String.Empty); return error; } } return null; }
// requires: The Where clause satisfies the same requirements a GetConjunctsFromWhereClause // effects: For each slot that has a NotNull condition in the where // clause, checks if it is projected. If all such slots are // projected, returns null. Else returns an error record internal ErrorLog.Record CheckForProjectedNotNullSlots(Cell sourceCell, IEnumerable<Cell> associationSets) { var builder = new StringBuilder(); var foundError = false; foreach (var restriction in Conditions) { if (restriction.Domain.ContainsNotNull()) { var slot = MemberProjectedSlot.GetSlotForMember(m_projectedSlots, restriction.RestrictedMemberSlot.MemberPath); if (slot == null) //member with not null condition is not mapped in this extent { var missingMapping = true; if (Extent is EntitySet) { var isCQuery = sourceCell.CQuery == this; var target = isCQuery ? ViewTarget.QueryView : ViewTarget.UpdateView; var rightCellQuery = isCQuery ? sourceCell.SQuery : sourceCell.CQuery; //Find out if there is an association mapping but only if the current Not Null condition is on an EntitySet var rightExtent = rightCellQuery.Extent as EntitySet; if (rightExtent != null) { var associations = MetadataHelper.GetAssociationsForEntitySet(rightCellQuery.Extent as EntitySet); foreach ( var association in associations.Where( association => association.AssociationSetEnds.Any( end => (end.CorrespondingAssociationEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One && (MetadataHelper.GetOppositeEnd(end).EntitySet.EdmEquals(rightExtent)))))) { foreach ( var associationCell in associationSets.Where(c => c.GetRightQuery(target).Extent.EdmEquals(association))) { if (MemberProjectedSlot.GetSlotForMember( associationCell.GetLeftQuery(target).ProjectedSlots, restriction.RestrictedMemberSlot.MemberPath) != null) { missingMapping = false; } } } } } if (missingMapping) { // condition of NotNull and slot not being projected builder.AppendLine( Strings.ViewGen_NotNull_No_Projected_Slot( restriction.RestrictedMemberSlot.MemberPath.PathToString(false))); foundError = true; } } } } if (false == foundError) { return null; } var record = new ErrorLog.Record(ViewGenErrorCode.NotNullNoProjectedSlot, builder.ToString(), sourceCell, String.Empty); return record; }
// requires: All slots in this are join tree slots // This method is called for an S-side query // cQuery is the corresponding C-side query in the cell // sourceCell is the original cell for "this" and cQuery // effects: Checks if any of the columns in "this" are mapped to multiple properties in cQuery. If so, // returns an error record about the duplicated slots internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell) { // slotMap stores the slots on the S-side and the // C-side properties that it maps to var slotMap = new KeyToListMap<MemberProjectedSlot, int>(ProjectedSlot.EqualityComparer); // Note that this does work for self-association. In the manager // employee example, ManagerId and EmployeeId from the SEmployee // table map to the two ends -- Manager.ManagerId and // Employee.EmployeeId in the C Space for (var i = 0; i < m_projectedSlots.Length; i++) { var projectedSlot = m_projectedSlots[i]; var slot = projectedSlot as MemberProjectedSlot; Debug.Assert(slot != null, "All slots for this method must be JoinTreeSlots"); slotMap.Add(slot, i); } StringBuilder builder = null; // Now determine the entries that have more than one integer per slot var isErrorSituation = false; foreach (var slot in slotMap.Keys) { var indexes = slotMap.ListForKey(slot); Debug.Assert(indexes.Count >= 1, "Each slot must have one index at least"); if (indexes.Count > 1 && cQuery.AreSlotsEquivalentViaRefConstraints(indexes) == false) { // The column is mapped to more than one property and it // failed the "association corresponds to referential // constraints" check isErrorSituation = true; if (builder == null) { builder = new StringBuilder(Strings.ViewGen_Duplicate_CProperties(Extent.Name)); builder.AppendLine(); } var tmpBuilder = new StringBuilder(); for (var i = 0; i < indexes.Count; i++) { var index = indexes[i]; if (i != 0) { tmpBuilder.Append(", "); } // The slot must be a JoinTreeSlot. If it isn't it is an internal error var cSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index]; tmpBuilder.Append(cSlot.ToUserString()); } builder.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped(slot.ToUserString(), tmpBuilder.ToString())); } } if (false == isErrorSituation) { return null; } var record = new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, builder.ToString(), sourceCell, String.Empty); return record; }
/// <summary> /// Given a cell, a member and a boolean condition on that member, creates additional cell /// which with the specified restriction on the member in addition to original condition. /// e.i conjunction of original condition AND member in newCondition /// Creation fails when the original condition contradicts new boolean condition /// ViewTarget tells whether MemberPath is in Cquery or SQuery /// </summary> private bool TryCreateAdditionalCellWithCondition( Cell originalCell, MemberPath memberToExpand, bool conditionValue, ViewTarget viewTarget, out Cell result) { DebugCheck.NotNull(originalCell); DebugCheck.NotNull(memberToExpand); result = null; //Create required structures var leftExtent = originalCell.GetLeftQuery(viewTarget).SourceExtentMemberPath; var rightExtent = originalCell.GetRightQuery(viewTarget).SourceExtentMemberPath; //Now for the given left-side projected member, find corresponding right-side member that it is mapped to var indexOfBooLMemberInProjection = originalCell.GetLeftQuery(viewTarget).GetProjectedMembers().TakeWhile(path => !path.Equals(memberToExpand)).Count(); var rightConditionMemberSlot = ((MemberProjectedSlot)originalCell.GetRightQuery(viewTarget).ProjectedSlotAt(indexOfBooLMemberInProjection)); var rightSidePath = rightConditionMemberSlot.MemberPath; var leftSlots = new List<ProjectedSlot>(); var rightSlots = new List<ProjectedSlot>(); //Check for impossible conditions (otehrwise we get inaccurate pre-validation errors) var negatedCondition = new ScalarConstant(!conditionValue); if (originalCell.GetLeftQuery(viewTarget).Conditions .Where(restriction => restriction.RestrictedMemberSlot.MemberPath.Equals(memberToExpand)) .Where(restriction => restriction.Domain.Values.Contains(negatedCondition)).Any() || originalCell.GetRightQuery(viewTarget).Conditions .Where(restriction => restriction.RestrictedMemberSlot.MemberPath.Equals(rightSidePath)) .Where(restriction => restriction.Domain.Values.Contains(negatedCondition)).Any()) { return false; } //End check //Create Projected Slots // Map all slots in original cell (not just keys) because some may be required (non nullable and no default) // and others may have not_null condition so MUST be projected. Rely on the user doing the right thing, otherwise // they will get the error message anyway for (var i = 0; i < originalCell.GetLeftQuery(viewTarget).NumProjectedSlots; i++) { leftSlots.Add(originalCell.GetLeftQuery(viewTarget).ProjectedSlotAt(i)); } for (var i = 0; i < originalCell.GetRightQuery(viewTarget).NumProjectedSlots; i++) { rightSlots.Add(originalCell.GetRightQuery(viewTarget).ProjectedSlotAt(i)); } //Create condition boolena expressions var leftQueryWhereClause = BoolExpression.CreateLiteral(new ScalarRestriction(memberToExpand, new ScalarConstant(conditionValue)), null); leftQueryWhereClause = BoolExpression.CreateAnd(originalCell.GetLeftQuery(viewTarget).WhereClause, leftQueryWhereClause); var rightQueryWhereClause = BoolExpression.CreateLiteral(new ScalarRestriction(rightSidePath, new ScalarConstant(conditionValue)), null); rightQueryWhereClause = BoolExpression.CreateAnd(originalCell.GetRightQuery(viewTarget).WhereClause, rightQueryWhereClause); //Create additional Cells var rightQuery = new CellQuery( rightSlots, rightQueryWhereClause, rightExtent, originalCell.GetRightQuery(viewTarget).SelectDistinctFlag); var leftQuery = new CellQuery( leftSlots, leftQueryWhereClause, leftExtent, originalCell.GetLeftQuery(viewTarget).SelectDistinctFlag); Cell newCell; if (viewTarget == ViewTarget.UpdateView) { newCell = Cell.CreateCS(rightQuery, leftQuery, originalCell.CellLabel, m_currentCellNumber); } else { newCell = Cell.CreateCS(leftQuery, rightQuery, originalCell.CellLabel, m_currentCellNumber); } m_currentCellNumber++; result = newCell; return true; }
// effects: Returns an error record if the keys of the extent/associationSet being mapped are // present in the projected slots of this query. Returns null // otherwise. ownerCell indicates the cell that owns this and // resourceString is a resource used for error messages internal ErrorLog.Record VerifyKeysPresent( Cell ownerCell, Func <object, object, string> formatEntitySetMessage, Func <object, object, object, string> formatAssociationSetMessage, ViewGenErrorCode errorCode) { var prefixes = new List <MemberPath>(1); // Keep track of the key corresponding to each prefix var keys = new List <ExtentKey>(1); if (Extent is EntitySet) { // For entity set just get the full path of the key properties var prefix = new MemberPath(Extent); prefixes.Add(prefix); var entityType = (EntityType)Extent.ElementType; var entitySetKeys = ExtentKey.GetKeysForEntityType(prefix, entityType); Debug.Assert(entitySetKeys.Count == 1, "Currently, we only support primary keys"); keys.Add(entitySetKeys[0]); } else { var relationshipSet = (AssociationSet)Extent; // For association set, get the full path of the key // properties of each end foreach (var relationEnd in relationshipSet.AssociationSetEnds) { var assocEndMember = relationEnd.CorrespondingAssociationEndMember; var prefix = new MemberPath(relationshipSet, assocEndMember); prefixes.Add(prefix); var endKeys = ExtentKey.GetKeysForEntityType( prefix, MetadataHelper.GetEntityTypeForEnd(assocEndMember)); Debug.Assert(endKeys.Count == 1, "Currently, we only support primary keys"); keys.Add(endKeys[0]); } } for (var i = 0; i < prefixes.Count; i++) { var prefix = prefixes[i]; // Get all or none key slots that are being projected in this cell query var keySlots = MemberProjectedSlot.GetKeySlots(GetMemberProjectedSlots(), prefix); if (keySlots == null) { var key = keys[i]; string message; if (Extent is EntitySet) { var keyPropertiesString = MemberPath.PropertiesToUserString(key.KeyFields, true); message = formatEntitySetMessage(keyPropertiesString, Extent.Name); } else { var endName = prefix.RootEdmMember.Name; var keyPropertiesString = MemberPath.PropertiesToUserString(key.KeyFields, false); message = formatAssociationSetMessage(keyPropertiesString, endName, Extent.Name); } var error = new ErrorLog.Record(errorCode, message, ownerCell, String.Empty); return(error); } } return(null); }
// requires: The Where clause satisfies the same requirements a GetConjunctsFromWhereClause // effects: For each slot that has a NotNull condition in the where // clause, checks if it is projected. If all such slots are // projected, returns null. Else returns an error record internal ErrorLog.Record CheckForProjectedNotNullSlots(Cell sourceCell, IEnumerable <Cell> associationSets) { var builder = new StringBuilder(); var foundError = false; foreach (var restriction in Conditions) { if (restriction.Domain.ContainsNotNull()) { var slot = MemberProjectedSlot.GetSlotForMember(m_projectedSlots, restriction.RestrictedMemberSlot.MemberPath); if (slot == null) //member with not null condition is not mapped in this extent { var missingMapping = true; if (Extent is EntitySet) { var isCQuery = sourceCell.CQuery == this; var target = isCQuery ? ViewTarget.QueryView : ViewTarget.UpdateView; var rightCellQuery = isCQuery ? sourceCell.SQuery : sourceCell.CQuery; //Find out if there is an association mapping but only if the current Not Null condition is on an EntitySet var rightExtent = rightCellQuery.Extent as EntitySet; if (rightExtent != null) { var associations = (rightCellQuery.Extent as EntitySet).AssociationSets; foreach ( var association in associations.Where( association => association.AssociationSetEnds.Any( end => (end.CorrespondingAssociationEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One && (MetadataHelper.GetOppositeEnd(end).EntitySet.EdmEquals(rightExtent)))))) { foreach ( var associationCell in associationSets.Where(c => c.GetRightQuery(target).Extent.EdmEquals(association))) { if (MemberProjectedSlot.GetSlotForMember( associationCell.GetLeftQuery(target).ProjectedSlots, restriction.RestrictedMemberSlot.MemberPath) != null) { missingMapping = false; } } } } } if (missingMapping) { // condition of NotNull and slot not being projected builder.AppendLine( Strings.ViewGen_NotNull_No_Projected_Slot( restriction.RestrictedMemberSlot.MemberPath.PathToString(false))); foundError = true; } } } } if (false == foundError) { return(null); } var record = new ErrorLog.Record(ViewGenErrorCode.NotNullNoProjectedSlot, builder.ToString(), sourceCell, String.Empty); return(record); }
// requires: All slots in this are join tree slots // This method is called for an S-side query // cQuery is the corresponding C-side query in the cell // sourceCell is the original cell for "this" and cQuery // effects: Checks if any of the columns in "this" are mapped to multiple properties in cQuery. If so, // returns an error record about the duplicated slots internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell) { // slotMap stores the slots on the S-side and the // C-side properties that it maps to var slotMap = new KeyToListMap <MemberProjectedSlot, int>(ProjectedSlot.EqualityComparer); // Note that this does work for self-association. In the manager // employee example, ManagerId and EmployeeId from the SEmployee // table map to the two ends -- Manager.ManagerId and // Employee.EmployeeId in the C Space for (var i = 0; i < m_projectedSlots.Length; i++) { var projectedSlot = m_projectedSlots[i]; var slot = projectedSlot as MemberProjectedSlot; Debug.Assert(slot != null, "All slots for this method must be JoinTreeSlots"); slotMap.Add(slot, i); } StringBuilder builder = null; // Now determine the entries that have more than one integer per slot var isErrorSituation = false; foreach (var slot in slotMap.Keys) { var indexes = slotMap.ListForKey(slot); Debug.Assert(indexes.Count >= 1, "Each slot must have one index at least"); if (indexes.Count > 1 && cQuery.AreSlotsEquivalentViaRefConstraints(indexes) == false) { // The column is mapped to more than one property and it // failed the "association corresponds to referential // constraints" check isErrorSituation = true; if (builder == null) { builder = new StringBuilder(Strings.ViewGen_Duplicate_CProperties(Extent.Name)); builder.AppendLine(); } var tmpBuilder = new StringBuilder(); for (var i = 0; i < indexes.Count; i++) { var index = indexes[i]; if (i != 0) { tmpBuilder.Append(", "); } // The slot must be a JoinTreeSlot. If it isn't it is an internal error var cSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index]; tmpBuilder.Append(cSlot.ToUserString()); } builder.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped(slot.ToUserString(), tmpBuilder.ToString())); } } if (false == isErrorSituation) { return(null); } var record = new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, builder.ToString(), sourceCell, String.Empty); return(record); }
internal Record(ViewGenErrorCode errorCode, string message, Cell sourceCell, string debugMessage) { Init(errorCode, message, new[] { sourceCell }, debugMessage); }
// effects: Returns true iff cell1 is an extent at the end of cell2's // relationship set or vice versa private static bool AreCellsConnectedViaRelationship(Cell cell1, Cell cell2) { var cRelationSet1 = cell1.CQuery.Extent as AssociationSet; var cRelationSet2 = cell2.CQuery.Extent as AssociationSet; if (cRelationSet1 != null && MetadataHelper.IsExtentAtSomeRelationshipEnd(cRelationSet1, cell2.CQuery.Extent)) { return true; } if (cRelationSet2 != null && MetadataHelper.IsExtentAtSomeRelationshipEnd(cRelationSet2, cell1.CQuery.Extent)) { return true; } return false; }
// effects: Returns true iff there is a foreign key constraint // between cell1 and cell2's S extents private bool OverlapViaForeignKeys(Cell cell1, Cell cell2) { var sExtent1 = cell1.SQuery.Extent; var sExtent2 = cell2.SQuery.Extent; foreach (var constraint in m_foreignKeyConstraints) { if (sExtent1.Equals(constraint.ParentTable) && sExtent2.Equals(constraint.ChildTable) || sExtent2.Equals(constraint.ParentTable) && sExtent1.Equals(constraint.ChildTable)) { return true; } } return false; }