internal override bool VisitLeaf(LeafCellTreeNode node, bool dummy) { CellQuery rightCellQuery1 = this.m_wrapper.RightCellQuery; CellQuery rightCellQuery2 = node.LeftCellWrapper.RightCellQuery; List <MemberPath> memberPathList = new List <MemberPath>(); if (rightCellQuery1 != rightCellQuery2) { for (int slotNum = 0; slotNum < rightCellQuery1.NumProjectedSlots; ++slotNum) { MemberProjectedSlot memberProjectedSlot1 = rightCellQuery1.ProjectedSlotAt(slotNum) as MemberProjectedSlot; if (memberProjectedSlot1 != null) { MemberProjectedSlot memberProjectedSlot2 = rightCellQuery2.ProjectedSlotAt(slotNum) as MemberProjectedSlot; if (memberProjectedSlot2 != null) { MemberPath projectedSlot = this.m_viewgenContext.MemberMaps.ProjectedSlotMap[slotNum]; if (!projectedSlot.IsPartOfKey && !MemberPath.EqualityComparer.Equals(memberProjectedSlot1.MemberPath, memberProjectedSlot2.MemberPath)) { memberPathList.Add(projectedSlot); } } } } } if (memberPathList.Count > 0) { this.m_errorLog.AddEntry(new ErrorLog.Record(ViewGenErrorCode.NonKeyProjectedWithOverlappingPartitions, Strings.ViewGen_NonKeyProjectedWithOverlappingPartitions((object)MemberPath.PropertiesToUserString((IEnumerable <MemberPath>)memberPathList, false)), (IEnumerable <LeftCellWrapper>) new LeftCellWrapper[2] { this.m_wrapper, node.LeftCellWrapper }, string.Empty)); } return(true); }
internal static string SlotToUserString(ViewCellSlot slot, bool isFromCside) { MemberProjectedSlot actualSlot = isFromCside ? slot.CSlot : slot.SSlot; string result = StringUtil.FormatInvariant("{0}", actualSlot); return(result); }
internal static BoolExpression PropagateCellConstantsToWhereClause( LeftCellWrapper wrapper, BoolExpression expression, Constant constant, MemberPath member, MemberMaps memberMaps) { MemberProjectedSlot mappedSlotForSmember = wrapper.GetCSideMappedSlotForSMember(member); if (mappedSlotForSmember == null) { return(expression); } NegatedConstant negatedConstant = constant as NegatedConstant; IEnumerable <Constant> domain = memberMaps.QueryDomainMap.GetDomain(mappedSlotForSmember.MemberPath); Set <Constant> set = new Set <Constant>(Constant.EqualityComparer); if (negatedConstant != null) { set.Unite(domain); set.Difference(negatedConstant.Elements); } else { set.Add(constant); } MemberRestriction memberRestriction = (MemberRestriction) new ScalarRestriction(mappedSlotForSmember.MemberPath, (IEnumerable <Constant>)set, domain); return(BoolExpression.CreateAnd(expression, BoolExpression.CreateLiteral((BoolLiteral)memberRestriction, memberMaps.QueryDomainMap))); }
internal ViewCellSlot LookupViewSlot(MemberProjectedSlot slot) { foreach (ViewCellSlot slot1 in this.m_slots) { if (ProjectedSlot.EqualityComparer.Equals((ProjectedSlot)slot, (ProjectedSlot)slot1.CSlot) || ProjectedSlot.EqualityComparer.Equals((ProjectedSlot)slot, (ProjectedSlot)slot1.SSlot)) { return(slot1); } } return((ViewCellSlot)null); }
// requires: slot corresponds to a slot in the corresponding // BasicCellRelation // effects: Given a slot in the corresponding basicCellRelation, // looks up the slot in this viewcellrelation and returns it. Returns // null if it does not find the slot in the left or right side of the viewrelation internal ViewCellSlot LookupViewSlot(MemberProjectedSlot slot) { // CHANGE_Microsoft_IMPROVE: We could have a dictionary to speed this up foreach (ViewCellSlot viewSlot in m_slots) { // If the left or right slots are equal, return the viewSlot if (ProjectedSlot.EqualityComparer.Equals(slot, viewSlot.CSlot) || ProjectedSlot.EqualityComparer.Equals(slot, viewSlot.SSlot)) { return viewSlot; } } return null; }
// effects: Given keys for this relation, adds one key constraint for // each key present in keys private void AddKeyConstraints(IEnumerable <ExtentKey> keys, BasicSchemaConstraints constraints) { foreach (var key in keys) { // If the key is being projected, only then do we add the key constraint var keySlots = MemberProjectedSlot.GetSlots(m_slots, key.KeyFields); if (keySlots != null) { var keyConstraint = new BasicKeyConstraint(this, keySlots); constraints.Add(keyConstraint); } } }
private void AddKeyConstraints( IEnumerable <ExtentKey> keys, SchemaConstraints <BasicKeyConstraint> constraints) { foreach (ExtentKey key in keys) { List <MemberProjectedSlot> slots = MemberProjectedSlot.GetSlots((IEnumerable <MemberProjectedSlot>) this.m_slots, key.KeyFields); if (slots != null) { BasicKeyConstraint constraint = new BasicKeyConstraint(this, (IEnumerable <MemberProjectedSlot>)slots); constraints.Add(constraint); } } }
private void CheckConstraintsOnProjectedConditionMembers( Dictionary <RewritingValidator.MemberValueBinding, CellTreeNode> memberValueTrees, LeftCellWrapper wrapper, CellTreeNode sQueryTree, BoolExpression inExtentCondition) { foreach (MemberPath conditionMember in this._domainMap.ConditionMembers(this._viewgenContext.Extent)) { int slotNum = this._viewgenContext.MemberMaps.ProjectedSlotMap.IndexOf(conditionMember); MemberProjectedSlot memberProjectedSlot = wrapper.RightCellQuery.ProjectedSlotAt(slotNum) as MemberProjectedSlot; if (memberProjectedSlot != null) { foreach (Constant constant in this._domainMap.GetDomain(conditionMember)) { CellTreeNode cellTreeNode1; if (memberValueTrees.TryGetValue(new RewritingValidator.MemberValueBinding(conditionMember, constant), out cellTreeNode1)) { FragmentQuery cQuery = FragmentQuery.Create(RewritingValidator.PropagateCellConstantsToWhereClause(wrapper, wrapper.RightCellQuery.WhereClause, constant, conditionMember, this._viewgenContext.MemberMaps)); CellTreeNode cellTreeNode2; if (sQueryTree != this._basicView) { cellTreeNode2 = (CellTreeNode) new OpCellTreeNode(this._viewgenContext, CellTreeOpType.IJ, new CellTreeNode[2] { cellTreeNode1, sQueryTree }); } else { cellTreeNode2 = cellTreeNode1; } CellTreeNode cellTreeNode3 = cellTreeNode2; BoolExpression unsatisfiedConstraint; if (!this.CheckEquivalence(cQuery, cellTreeNode3.RightFragmentQuery, inExtentCondition, out unsatisfiedConstraint)) { this.ReportConstraintViolation(Strings.ViewGen_CQ_DomainConstraint((object)memberProjectedSlot.ToUserString()), unsatisfiedConstraint, ViewGenErrorCode.DomainConstraintViolation, cellTreeNode3.GetLeaves().Concat <LeftCellWrapper>((IEnumerable <LeftCellWrapper>) new LeftCellWrapper[1] { wrapper })); } } } } } }
private static FragmentQuery AddNullConditionOnCSideFragment( LeftCellWrapper wrapper, MemberPath member, MemberMaps memberMaps) { MemberProjectedSlot mappedSlotForSmember = wrapper.GetCSideMappedSlotForSMember(member); if (mappedSlotForSmember == null || !mappedSlotForSmember.MemberPath.IsNullable) { return((FragmentQuery)null); } BoolExpression whereClause = wrapper.RightCellQuery.WhereClause; IEnumerable <Constant> domain = memberMaps.QueryDomainMap.GetDomain(mappedSlotForSmember.MemberPath); MemberRestriction memberRestriction = (MemberRestriction) new ScalarRestriction(mappedSlotForSmember.MemberPath, (IEnumerable <Constant>) new Set <Constant>(Constant.EqualityComparer) { Constant.Null }, domain); return(FragmentQuery.Create(BoolExpression.CreateAnd(whereClause, BoolExpression.CreateLiteral((BoolLiteral)memberRestriction, memberMaps.QueryDomainMap)))); }
/// <summary> /// Given a LeftCellWrapper for the S-side fragment and a non-nullable colum m, return a CQuery with nullability condition /// appended to Cquery of c-side member that column m is mapped to /// </summary> private static FragmentQuery AddNullConditionOnCSideFragment(LeftCellWrapper wrapper, MemberPath member, MemberMaps memberMaps) { MemberProjectedSlot projectedSlot = wrapper.GetCSideMappedSlotForSMember(member); if (projectedSlot == null || !projectedSlot.MemberPath.IsNullable) //don't bother checking further fore non nullable C-side member { return(null); } BoolExpression expression = wrapper.RightCellQuery.WhereClause; IEnumerable <Constant> possibleValues = memberMaps.QueryDomainMap.GetDomain(projectedSlot.MemberPath); Set <Constant> allowedValues = new Set <Constant>(Constant.EqualityComparer); allowedValues.Add(Constant.Null); //Create a condition as conjunction of originalCondition and slot IS NULL MemberRestriction restriction = new ScalarRestriction(projectedSlot.MemberPath, allowedValues, possibleValues); BoolExpression resultingExpr = BoolExpression.CreateAnd(expression, BoolExpression.CreateLiteral(restriction, memberMaps.QueryDomainMap)); return(FragmentQuery.Create(resultingExpr)); }
internal override bool VisitLeaf(LeafCellTreeNode node, bool dummy) { // make sure all projected attributes in wrapper correspond exactly to those in node CellQuery thisQuery = m_wrapper.RightCellQuery; CellQuery thatQuery = node.LeftCellWrapper.RightCellQuery; List <MemberPath> collidingColumns = new List <MemberPath>(); if (thisQuery != thatQuery) { for (int i = 0; i < thisQuery.NumProjectedSlots; i++) { MemberProjectedSlot thisSlot = thisQuery.ProjectedSlotAt(i) as MemberProjectedSlot; if (thisSlot != null) { MemberProjectedSlot thatSlot = thatQuery.ProjectedSlotAt(i) as MemberProjectedSlot; if (thatSlot != null) { MemberPath tableMember = m_viewgenContext.MemberMaps.ProjectedSlotMap[i]; if (!tableMember.IsPartOfKey) { if (!MemberPath.EqualityComparer.Equals(thisSlot.MemberPath, thatSlot.MemberPath)) { collidingColumns.Add(tableMember); } } } } } } if (collidingColumns.Count > 0) { string columnsString = MemberPath.PropertiesToUserString(collidingColumns, false); string message = Strings.ViewGen_NonKeyProjectedWithOverlappingPartitions(columnsString); ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.NonKeyProjectedWithOverlappingPartitions, message, new LeftCellWrapper[] { m_wrapper, node.LeftCellWrapper }, String.Empty); m_errorLog.AddEntry(record); } return(true); }
// effects: Given a sequence of constants that need to be propagated // to the C-side and the current boolean expression, generates a new // expression of the form "expression AND C-side Member in constants" // expression" and returns it. Each constant is propagated only if member // is projected -- if member is not projected, returns "expression" internal static BoolExpression PropagateCellConstantsToWhereClause(LeftCellWrapper wrapper, BoolExpression expression, Constant constant, MemberPath member, MemberMaps memberMaps) { MemberProjectedSlot joinSlot = wrapper.GetCSideMappedSlotForSMember(member); if (joinSlot == null) { return(expression); } // Look at the constants and determine if they correspond to // typeConstants or scalarConstants // This slot is being projected. We need to add a where clause element Debug.Assert(constant is ScalarConstant || constant.IsNull() || constant is NegatedConstant, "Invalid type of constant"); // We want the possible values for joinSlot.MemberPath which is a // C-side element -- so we use the queryDomainMap IEnumerable <Constant> possibleValues = memberMaps.QueryDomainMap.GetDomain(joinSlot.MemberPath); // Note: the values in constaints can be null or not null as // well (i.e., just not scalarConstants) Set <Constant> allowedValues = new Set <Constant>(Constant.EqualityComparer); if (constant is NegatedConstant) { // select all values from the c-side domain that are not in the negated set allowedValues.Unite(possibleValues); allowedValues.Difference(((NegatedConstant)constant).Elements); } else { allowedValues.Add(constant); } MemberRestriction restriction = new ScalarRestriction(joinSlot.MemberPath, allowedValues, possibleValues); BoolExpression result = BoolExpression.CreateAnd(expression, BoolExpression.CreateLiteral(restriction, memberMaps.QueryDomainMap)); return(result); }
private void CheckConstraintsOnProjectedConditionMembers(Dictionary <MemberValueBinding, CellTreeNode> memberValueTrees, LeftCellWrapper wrapper, CellTreeNode sQueryTree, BoolExpression inExtentCondition) { // for S-side condition members that are projected, // add condition <member=value> on both sides of the mapping constraint, and check key equivalence // applies to columns that are (1) projected and (2) conditional foreach (MemberPath column in _domainMap.ConditionMembers(_viewgenContext.Extent)) { // Get the slot on the C side and see if it is projected int index = _viewgenContext.MemberMaps.ProjectedSlotMap.IndexOf(column); MemberProjectedSlot slot = wrapper.RightCellQuery.ProjectedSlotAt(index) as MemberProjectedSlot; if (slot != null) { foreach (Constant domainValue in _domainMap.GetDomain(column)) { CellTreeNode sQueryTreeForDomainValue; if (memberValueTrees.TryGetValue(new MemberValueBinding(column, domainValue), out sQueryTreeForDomainValue)) { BoolExpression cWhereClause = PropagateCellConstantsToWhereClause(wrapper, wrapper.RightCellQuery.WhereClause, domainValue, column, _viewgenContext.MemberMaps); FragmentQuery cCombinedQuery = FragmentQuery.Create(cWhereClause); CellTreeNode sCombinedTree = (sQueryTree == _basicView) ? sQueryTreeForDomainValue : new OpCellTreeNode(_viewgenContext, CellTreeOpType.IJ, sQueryTreeForDomainValue, sQueryTree); BoolExpression unsatisfiedConstraint; if (!CheckEquivalence(cCombinedQuery, sCombinedTree.RightFragmentQuery, inExtentCondition, out unsatisfiedConstraint)) { string memberLossMessage = Strings.ViewGen_CQ_DomainConstraint(slot.ToUserString()); ReportConstraintViolation(memberLossMessage, unsatisfiedConstraint, ViewGenErrorCode.DomainConstraintViolation, sCombinedTree.GetLeaves().Concat(new LeftCellWrapper[] { wrapper })); } } } } } }
internal ViewCellSlot(int slotNum, MemberProjectedSlot cSlot, MemberProjectedSlot sSlot) { this.m_slotNum = slotNum; this.m_cSlot = cSlot; this.m_sSlot = sSlot; }
/// <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) { Debug.Assert(originalCell != null); Debug.Assert(memberToExpand != null); result = null; //Create required structures MemberPath leftExtent = originalCell.GetLeftQuery(viewTarget).SourceExtentMemberPath; MemberPath rightExtent = originalCell.GetRightQuery(viewTarget).SourceExtentMemberPath; //Now for the given left-side projected member, find corresponding right-side member that it is mapped to int indexOfBooLMemberInProjection = originalCell.GetLeftQuery(viewTarget).GetProjectedMembers().TakeWhile(path => !path.Equals(memberToExpand)).Count(); MemberProjectedSlot rightConditionMemberSlot = ((MemberProjectedSlot)originalCell.GetRightQuery(viewTarget).ProjectedSlotAt(indexOfBooLMemberInProjection)); MemberPath rightSidePath = rightConditionMemberSlot.MemberPath; List <ProjectedSlot> leftSlots = new List <ProjectedSlot>(); List <ProjectedSlot> rightSlots = new List <ProjectedSlot>(); //Check for impossible conditions (otehrwise we get inaccurate pre-validation errors) ScalarConstant 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 (int i = 0; i < originalCell.GetLeftQuery(viewTarget).NumProjectedSlots; i++) { leftSlots.Add(originalCell.GetLeftQuery(viewTarget).ProjectedSlotAt(i)); } for (int i = 0; i < originalCell.GetRightQuery(viewTarget).NumProjectedSlots; i++) { rightSlots.Add(originalCell.GetRightQuery(viewTarget).ProjectedSlotAt(i)); } //Create condition boolena expressions BoolExpression leftQueryWhereClause = BoolExpression.CreateLiteral(new ScalarRestriction(memberToExpand, new ScalarConstant(conditionValue)), null); leftQueryWhereClause = BoolExpression.CreateAnd(originalCell.GetLeftQuery(viewTarget).WhereClause, leftQueryWhereClause); BoolExpression rightQueryWhereClause = BoolExpression.CreateLiteral(new ScalarRestriction(rightSidePath, new ScalarConstant(conditionValue)), null); rightQueryWhereClause = BoolExpression.CreateAnd(originalCell.GetRightQuery(viewTarget).WhereClause, rightQueryWhereClause); //Create additional Cells CellQuery rightQuery = new CellQuery(rightSlots, rightQueryWhereClause, rightExtent, originalCell.GetRightQuery(viewTarget).SelectDistinctFlag); CellQuery 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); }
// requires: all columns in constraint.ParentColumns and // constraint.ChildColumns must have been mapped in some cell in m_cellGroup // effects: Given the foreign key constraint, checks if the // constraint.ChildColumns are mapped to the constraint.ParentColumns // in m_cellGroup in the right oder. If not, adds an error to m_errorLog and returns // false. Else returns true private bool CheckForeignKeyColumnOrder(Set <Cell> cells, ErrorLog errorLog) { // Go through every cell and find the cells that are relevant to // parent and those that are relevant to child // Then for each cell pair (parent, child) make sure that the // projected foreign keys columns in C-space are aligned List <Cell> parentCells = new List <Cell>(); List <Cell> childCells = new List <Cell>(); foreach (Cell cell in cells) { if (cell.SQuery.Extent.Equals(ChildTable)) { childCells.Add(cell); } if (cell.SQuery.Extent.Equals(ParentTable)) { parentCells.Add(cell); } } // Make sure that all child cells and parent cells align on // the columns, i.e., for each DISTINCT pair C and P, get the columns // on the S-side. Then get the corresponding fields on the // C-side. The fields on the C-side should match bool foundParentCell = false; bool foundChildCell = false; foreach (Cell childCell in childCells) { List <List <int> > allChildSlotNums = GetSlotNumsForColumns(childCell, ChildColumns); if (allChildSlotNums.Count == 0) { // slots in present in S-side, ignore continue; } List <MemberPath> childPaths = null; List <MemberPath> parentPaths = null; Cell errorParentCell = null; foreach (List <int> childSlotNums in allChildSlotNums) { foundChildCell = true; // Get the fields on the C-side childPaths = new List <MemberPath>(childSlotNums.Count); foreach (int childSlotNum in childSlotNums) { // Initial slots only have JoinTreeSlots MemberProjectedSlot childSlot = (MemberProjectedSlot)childCell.CQuery.ProjectedSlotAt(childSlotNum); Debug.Assert(childSlot != null); childPaths.Add(childSlot.MemberPath); } foreach (Cell parentCell in parentCells) { List <List <int> > allParentSlotNums = GetSlotNumsForColumns(parentCell, ParentColumns); if (allParentSlotNums.Count == 0) { // * Parent and child cell are the same - we do not // need to check since we want to check the foreign // key constraint mapping across cells // * Some slots not in present in S-side, ignore continue; } foreach (List <int> parentSlotNums in allParentSlotNums) { foundParentCell = true; parentPaths = new List <MemberPath>(parentSlotNums.Count); foreach (int parentSlotNum in parentSlotNums) { MemberProjectedSlot parentSlot = (MemberProjectedSlot)parentCell.CQuery.ProjectedSlotAt(parentSlotNum); Debug.Assert(parentSlot != null); parentPaths.Add(parentSlot.MemberPath); } // Make sure that the last member of each of these is the same // or the paths are essentially equivalent via referential constraints // We need to check that the last member is essentially the same because it could // be a regular scenario where aid is mapped to PersonAddress and Address - there // is no ref constraint. So when projected into C-Space, we will get Address.aid // and PersonAddress.Address.aid if (childPaths.Count == parentPaths.Count) { bool notAllPathsMatched = false; for (int i = 0; i < childPaths.Count && !notAllPathsMatched; i++) { MemberPath parentPath = parentPaths[i]; MemberPath childPath = childPaths[i]; if (!parentPath.LeafEdmMember.Equals(childPath.LeafEdmMember)) //Child path did not match { if (parentPath.IsEquivalentViaRefConstraint(childPath)) { //Specifying the referential constraint once in the C space should be enough. //This is the only way possible today. //We might be able to derive more knowledge by using boolean logic return(true); } else { notAllPathsMatched = true; } } } if (!notAllPathsMatched) { return(true); //all childPaths matched parentPaths } else { //If not this one, some other Parent Cell may match. errorParentCell = parentCell; } } } } //foreach parentCell } //If execution is at this point, no parent cell's end has matched (otherwise it would have returned true) Debug.Assert(childPaths != null, "child paths should be set"); Debug.Assert(parentPaths != null, "parent paths should be set"); Debug.Assert(errorParentCell != null, "errorParentCell should be set"); // using EntityRes. instead of Strings. because the generated method includes 6 instead of 9 parameters string message = EntityRes.GetString(EntityRes.ViewGen_Foreign_Key_ColumnOrder_Incorrect, ToUserString(), MemberPath.PropertiesToUserString(ChildColumns, false), ChildTable.Name, MemberPath.PropertiesToUserString(childPaths, false), childCell.CQuery.Extent.Name, MemberPath.PropertiesToUserString(ParentColumns, false), ParentTable.Name, MemberPath.PropertiesToUserString(parentPaths, false), errorParentCell.CQuery.Extent.Name); ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ForeignKeyColumnOrderIncorrect, message, new Cell[] { errorParentCell, childCell }, String.Empty); errorLog.AddEntry(record); return(false); } Debug.Assert(foundParentCell == true, "Some cell that mapped the parent's key must be present!"); Debug.Assert(foundChildCell == true, "Some cell that mapped the child's foreign key must be present according to the requires clause!"); return(true); }
private bool CheckForeignKeyColumnOrder(Set <Cell> cells, ErrorLog errorLog) { List <Cell> cellList1 = new List <Cell>(); List <Cell> cellList2 = new List <Cell>(); foreach (Cell cell in cells) { if (cell.SQuery.Extent.Equals((object)this.ChildTable)) { cellList2.Add(cell); } if (cell.SQuery.Extent.Equals((object)this.ParentTable)) { cellList1.Add(cell); } } foreach (Cell cell1 in cellList2) { List <List <int> > slotNumsForColumns1 = ForeignConstraint.GetSlotNumsForColumns(cell1, this.ChildColumns); if (slotNumsForColumns1.Count != 0) { List <MemberPath> memberPathList1 = (List <MemberPath>)null; List <MemberPath> memberPathList2 = (List <MemberPath>)null; Cell cell2 = (Cell)null; foreach (List <int> intList1 in slotNumsForColumns1) { memberPathList1 = new List <MemberPath>(intList1.Count); foreach (int slotNum in intList1) { MemberProjectedSlot memberProjectedSlot = (MemberProjectedSlot)cell1.CQuery.ProjectedSlotAt(slotNum); memberPathList1.Add(memberProjectedSlot.MemberPath); } foreach (Cell cell3 in cellList1) { List <List <int> > slotNumsForColumns2 = ForeignConstraint.GetSlotNumsForColumns(cell3, this.ParentColumns); if (slotNumsForColumns2.Count != 0) { foreach (List <int> intList2 in slotNumsForColumns2) { memberPathList2 = new List <MemberPath>(intList2.Count); foreach (int slotNum in intList2) { MemberProjectedSlot memberProjectedSlot = (MemberProjectedSlot)cell3.CQuery.ProjectedSlotAt(slotNum); memberPathList2.Add(memberProjectedSlot.MemberPath); } if (memberPathList1.Count == memberPathList2.Count) { bool flag = false; for (int index = 0; index < memberPathList1.Count && !flag; ++index) { MemberPath memberPath = memberPathList2[index]; MemberPath path1 = memberPathList1[index]; if (!memberPath.LeafEdmMember.Equals((object)path1.LeafEdmMember)) { if (memberPath.IsEquivalentViaRefConstraint(path1)) { return(true); } flag = true; } } if (!flag) { return(true); } cell2 = cell3; } } } } } ErrorLog.Record record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyColumnOrderIncorrect, Strings.ViewGen_Foreign_Key_ColumnOrder_Incorrect((object)this.ToUserString(), (object)MemberPath.PropertiesToUserString(this.ChildColumns, false), (object)this.ChildTable.Name, (object)MemberPath.PropertiesToUserString((IEnumerable <MemberPath>)memberPathList1, false), (object)cell1.CQuery.Extent.Name, (object)MemberPath.PropertiesToUserString(this.ParentColumns, false), (object)this.ParentTable.Name, (object)MemberPath.PropertiesToUserString((IEnumerable <MemberPath>)memberPathList2, false), (object)cell2.CQuery.Extent.Name), (IEnumerable <Cell>) new Cell[2] { cell2, cell1 }, string.Empty); errorLog.AddEntry(record); return(false); } } return(true); }