Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / LeftCellWrapper.cs / 2 / LeftCellWrapper.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common.Utils; using System.Text; using System.Linq; using System.Diagnostics; using System.Collections.ObjectModel; using System.Data.Metadata.Edm; using System.Data.Common.Utils.Boolean; using System.Data.Mapping.ViewGeneration.Validation; using System.Data.Mapping.ViewGeneration.QueryRewriting; namespace System.Data.Mapping.ViewGeneration.Structures { // This class essentially stores a cell but in a special form. When we // are generating a view for an extent, we denote the extent's side (C or // S) as the "left side" and the side being used in the view as the right // side. For example, in query views, the C side is the left side. // // Each LeftCellWrapper is a cell of the form: // Project[A1,...,An] (Select[var IN {domain}] (Extent)) = Expr // Where // - "domain" is a set of multiconstants that correspond to the different // variable values allowed for the cell query // - A1 ... An are denoted by Attributes in this and corresponds to // the list of attributes that are projected // - Extent is the extent for which th view is being generated // - Expr is the expression on the other side to produce the left side of // the cell internal class LeftCellWrapper : InternalBase { #region Constructor // effects: Creates a LeftCellWrapper of the form: // Project[attrs] (Select[var IN {domain}] (Extent)) = cellquery // memberMaps is the set of maps used for producing the query or update views internal LeftCellWrapper(SchemaContext schemaContext, Setattrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, IEnumerable inputCells) { m_fragmentQuery = fragmentQuery; m_rightCellQuery = cellQuery; m_attributes = attrs; m_schemaContext = schemaContext; m_memberMaps = memberMaps; m_cells = new HashSet | (inputCells); } internal LeftCellWrapper(SchemaContext schemaContext, Set | attrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, Cell inputCell) : this(schemaContext, attrs, fragmentQuery, cellQuery, memberMaps, new Cell[] { inputCell }) { } #endregion #region Fields internal static readonly IEqualityComparer BoolEqualityComparer = new BoolWrapperComparer(); private Set m_attributes;// project: attributes computed by // Expr (projected attributes that get set) private MemberMaps m_memberMaps; private CellQuery m_rightCellQuery; // expression that computes this portion private HashSet m_cells; private SchemaContext m_schemaContext; private FragmentQuery m_fragmentQuery; // fragment query corresponding to the left cell query of the cell internal static readonly IComparer | Comparer = new LeftCellWrapperComparer(); internal static readonly IComparer OriginalCellIdComparer = new CellIdComparer(); #endregion #region Properties internal FragmentQuery FragmentQuery { get { return m_fragmentQuery; } } internal SchemaContext SchemaContext { get { return m_schemaContext;} } // effects: Returns the projected fields on the left side internal Set Attributes { get { return m_attributes; } } // effects: Returns the original cell number from which the wrapper came internal string OriginalCellNumberString { get { return StringUtil.ToSeparatedString(m_cells.Select(cell => cell.CellNumberAsString), "+", ""); } } // effects: Returns the right domain map associated with the right query internal MemberDomainMap RightDomainMap { get { return m_memberMaps.RightDomainMap; } } [Conditional("DEBUG")] internal void AssertHasUniqueCell() { Debug.Assert(m_cells.Count == 1); } internal IEnumerable Cells { get { return m_cells; } } // requires: There is only one input cell in this // effects: Returns the input cell provided to view generation as part of the mapping internal Cell OnlyInputCell { get { AssertHasUniqueCell(); return m_cells.First(); } } // effects: Returns the right CellQuery internal CellQuery RightCellQuery { get { return m_rightCellQuery; } } // effects: Returns the extent for which the wrapper was built internal EntitySetBase LeftExtent { get { return m_cells.First().GetLeftQuery(m_schemaContext.ViewTarget).Extent; } } // effects: Returns the extent of the right cellquery internal EntitySetBase RightExtent { get { EntitySetBase result = m_rightCellQuery.Extent; Debug.Assert(result != null, "Bad root value in join tree"); return result; } } #endregion #region Methods // effects: Yields the input cells in wrappers internal static IEnumerable | GetInputCellsForWrappers(IEnumerable | wrappers) { foreach (LeftCellWrapper wrapper in wrappers) { foreach (Cell cell in wrapper.m_cells) { yield return cell; } } } // requires: RightCellQuery.Extent corresponds to a relationship set // effects: Returns the ends to which the key of the corresponding // table (i.e., the left query) maps to in the relationship set. For // example, if RightCellQuery.Extent is OrderOrders and it maps to // of table SOrders with key oid, this returns the // end to which oid is mapped. Similarly, if we have a link table // with the whole key mapped to two ends of the association set, it // returns both ends private Set GetEndsForTablePrimaryKey() { CellQuery rightQuery = RightCellQuery; Set result = new Set (EqualityComparer .Default); // Get the key slots for the table (they are in the slotMap) and // check for that slot on the C-side foreach (int keySlot in m_memberMaps.ProjectedSlotMap.KeySlots) { JoinTreeSlot slot = (JoinTreeSlot)rightQuery.ProjectedSlotAt(keySlot); MemberPath path = slot.MemberPath; // See what end it maps to in the relationSet AssociationEndMember endMember = (AssociationEndMember)path.FirstMember; Debug.Assert(endMember != null, "Element in path before scalar path is not end property?"); result.Add(endMember); } Debug.Assert(result != null, "No end found for keyslots of table?"); return result; } // effects: Creates a boolean variable representing the right extent or association end internal RoleBoolean CreateRoleBoolean() { if (RightExtent is AssociationSet) { Set ends = GetEndsForTablePrimaryKey(); if (ends.Count == 1) { AssociationSetEnd setEnd = ((AssociationSet)RightExtent).AssociationSetEnds[ends.First().Name]; return new RoleBoolean(setEnd); } } return new RoleBoolean(RightExtent); } // effects: Given a set of wrappers, returns a string that contains the list of extents in the // rightcellQueries of the wrappers internal static string GetExtentListAsUserString(IEnumerable wrappers) { Set extents = new Set (EqualityComparer .Default); foreach (LeftCellWrapper wrapper in wrappers) { extents.Add(wrapper.RightExtent); } StringBuilder builder = new StringBuilder(); bool isFirst = true; foreach (EntitySetBase extent in extents) { if (isFirst == false) { builder.Append(", "); } isFirst = false; builder.Append(extent.Name); } return builder.ToString(); } internal override void ToFullString(StringBuilder builder) { builder.Append("P["); StringUtil.ToSeparatedString(builder, m_attributes, ","); builder.Append("] = "); m_rightCellQuery.ToFullString(builder); } // effects: Modifies stringBuilder to contain the view corresponding // to the right cellquery internal override void ToCompactString(StringBuilder stringBuilder) { stringBuilder.Append(OriginalCellNumberString); } // effects: Writes m_cellWrappers to builder internal static void WrappersToStringBuilder(StringBuilder builder, List wrappers, string header) { builder.AppendLine() .Append(header) .AppendLine(); // Sort them according to the original cell number LeftCellWrapper[] cellWrappers = wrappers.ToArray(); Array.Sort(cellWrappers, LeftCellWrapper.OriginalCellIdComparer); foreach (LeftCellWrapper wrapper in cellWrappers) { wrapper.ToCompactString(builder); builder.Append(" = "); wrapper.ToFullString(builder); builder.AppendLine(); } } #endregion #region Equality Comparer class // This class compares wrappers based on the Right Where Clause and // Extent -- needed for the boolean engine private class BoolWrapperComparer : IEqualityComparer { public bool Equals(LeftCellWrapper left, LeftCellWrapper right) { // Quick check with references if (object.ReferenceEquals(left, right)) { // Gets the Null and Undefined case as well return true; } // One of them is non-null at least if (left == null || right == null) { return false; } // Both are non-null at this point bool whereClauseEqual = BoolExpression.EqualityComparer.Equals(left.RightCellQuery.WhereClause, right.RightCellQuery.WhereClause); return left.RightExtent.Equals(right.RightExtent) && whereClauseEqual; } public int GetHashCode(LeftCellWrapper wrapper) { return BoolExpression.EqualityComparer.GetHashCode(wrapper.RightCellQuery.WhereClause) ^ wrapper.RightExtent.GetHashCode(); } } #endregion #region Comparer // A class that compares two cell wrappers. Useful for guiding heuristics // and to ensure that the largest selection domain (i.e., the number of // multiconstants in "mc in {...}") is first in the list private class LeftCellWrapperComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { // More attributes first -- so that we get most attributes // with very few intersections (when we use the sortings for // that). When we are subtracting, attributes are not important // Use FragmentQuery's attributes instead of LeftCellWrapper's original attributes in the comparison // since the former might have got extended to include all attributes whose value is determined // by the WHERE clause (e.g., if we have WHERE ProductName='Camera' we can assume ProductName is projected) if (x.FragmentQuery.Attributes.Count > y.FragmentQuery.Attributes.Count) { return -1; } else if (x.FragmentQuery.Attributes.Count < y.FragmentQuery.Attributes.Count) { return 1; } // Since the sort may not be stable, we use the original cell number string to break the tie return String.CompareOrdinal(x.OriginalCellNumberString, y.OriginalCellNumberString); } } // A class that compares two cell wrappers based on original cell number internal class CellIdComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { return StringComparer.Ordinal.Compare(x.OriginalCellNumberString, y.OriginalCellNumberString); } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common.Utils; using System.Text; using System.Linq; using System.Diagnostics; using System.Collections.ObjectModel; using System.Data.Metadata.Edm; using System.Data.Common.Utils.Boolean; using System.Data.Mapping.ViewGeneration.Validation; using System.Data.Mapping.ViewGeneration.QueryRewriting; namespace System.Data.Mapping.ViewGeneration.Structures { // This class essentially stores a cell but in a special form. When we // are generating a view for an extent, we denote the extent's side (C or // S) as the "left side" and the side being used in the view as the right // side. For example, in query views, the C side is the left side. // // Each LeftCellWrapper is a cell of the form: // Project[A1,...,An] (Select[var IN {domain}] (Extent)) = Expr // Where // - "domain" is a set of multiconstants that correspond to the different // variable values allowed for the cell query // - A1 ... An are denoted by Attributes in this and corresponds to // the list of attributes that are projected // - Extent is the extent for which th view is being generated // - Expr is the expression on the other side to produce the left side of // the cell internal class LeftCellWrapper : InternalBase { #region Constructor // effects: Creates a LeftCellWrapper of the form: // Project[attrs] (Select[var IN {domain}] (Extent)) = cellquery // memberMaps is the set of maps used for producing the query or update views internal LeftCellWrapper(SchemaContext schemaContext, Setattrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, IEnumerable inputCells) { m_fragmentQuery = fragmentQuery; m_rightCellQuery = cellQuery; m_attributes = attrs; m_schemaContext = schemaContext; m_memberMaps = memberMaps; m_cells = new HashSet | (inputCells); } internal LeftCellWrapper(SchemaContext schemaContext, Set | attrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, Cell inputCell) : this(schemaContext, attrs, fragmentQuery, cellQuery, memberMaps, new Cell[] { inputCell }) { } #endregion #region Fields internal static readonly IEqualityComparer BoolEqualityComparer = new BoolWrapperComparer(); private Set m_attributes;// project: attributes computed by // Expr (projected attributes that get set) private MemberMaps m_memberMaps; private CellQuery m_rightCellQuery; // expression that computes this portion private HashSet m_cells; private SchemaContext m_schemaContext; private FragmentQuery m_fragmentQuery; // fragment query corresponding to the left cell query of the cell internal static readonly IComparer | Comparer = new LeftCellWrapperComparer(); internal static readonly IComparer OriginalCellIdComparer = new CellIdComparer(); #endregion #region Properties internal FragmentQuery FragmentQuery { get { return m_fragmentQuery; } } internal SchemaContext SchemaContext { get { return m_schemaContext;} } // effects: Returns the projected fields on the left side internal Set Attributes { get { return m_attributes; } } // effects: Returns the original cell number from which the wrapper came internal string OriginalCellNumberString { get { return StringUtil.ToSeparatedString(m_cells.Select(cell => cell.CellNumberAsString), "+", ""); } } // effects: Returns the right domain map associated with the right query internal MemberDomainMap RightDomainMap { get { return m_memberMaps.RightDomainMap; } } [Conditional("DEBUG")] internal void AssertHasUniqueCell() { Debug.Assert(m_cells.Count == 1); } internal IEnumerable Cells { get { return m_cells; } } // requires: There is only one input cell in this // effects: Returns the input cell provided to view generation as part of the mapping internal Cell OnlyInputCell { get { AssertHasUniqueCell(); return m_cells.First(); } } // effects: Returns the right CellQuery internal CellQuery RightCellQuery { get { return m_rightCellQuery; } } // effects: Returns the extent for which the wrapper was built internal EntitySetBase LeftExtent { get { return m_cells.First().GetLeftQuery(m_schemaContext.ViewTarget).Extent; } } // effects: Returns the extent of the right cellquery internal EntitySetBase RightExtent { get { EntitySetBase result = m_rightCellQuery.Extent; Debug.Assert(result != null, "Bad root value in join tree"); return result; } } #endregion #region Methods // effects: Yields the input cells in wrappers internal static IEnumerable | GetInputCellsForWrappers(IEnumerable | wrappers) { foreach (LeftCellWrapper wrapper in wrappers) { foreach (Cell cell in wrapper.m_cells) { yield return cell; } } } // requires: RightCellQuery.Extent corresponds to a relationship set // effects: Returns the ends to which the key of the corresponding // table (i.e., the left query) maps to in the relationship set. For // example, if RightCellQuery.Extent is OrderOrders and it maps to // of table SOrders with key oid, this returns the // end to which oid is mapped. Similarly, if we have a link table // with the whole key mapped to two ends of the association set, it // returns both ends private Set GetEndsForTablePrimaryKey() { CellQuery rightQuery = RightCellQuery; Set result = new Set (EqualityComparer .Default); // Get the key slots for the table (they are in the slotMap) and // check for that slot on the C-side foreach (int keySlot in m_memberMaps.ProjectedSlotMap.KeySlots) { JoinTreeSlot slot = (JoinTreeSlot)rightQuery.ProjectedSlotAt(keySlot); MemberPath path = slot.MemberPath; // See what end it maps to in the relationSet AssociationEndMember endMember = (AssociationEndMember)path.FirstMember; Debug.Assert(endMember != null, "Element in path before scalar path is not end property?"); result.Add(endMember); } Debug.Assert(result != null, "No end found for keyslots of table?"); return result; } // effects: Creates a boolean variable representing the right extent or association end internal RoleBoolean CreateRoleBoolean() { if (RightExtent is AssociationSet) { Set ends = GetEndsForTablePrimaryKey(); if (ends.Count == 1) { AssociationSetEnd setEnd = ((AssociationSet)RightExtent).AssociationSetEnds[ends.First().Name]; return new RoleBoolean(setEnd); } } return new RoleBoolean(RightExtent); } // effects: Given a set of wrappers, returns a string that contains the list of extents in the // rightcellQueries of the wrappers internal static string GetExtentListAsUserString(IEnumerable wrappers) { Set extents = new Set (EqualityComparer .Default); foreach (LeftCellWrapper wrapper in wrappers) { extents.Add(wrapper.RightExtent); } StringBuilder builder = new StringBuilder(); bool isFirst = true; foreach (EntitySetBase extent in extents) { if (isFirst == false) { builder.Append(", "); } isFirst = false; builder.Append(extent.Name); } return builder.ToString(); } internal override void ToFullString(StringBuilder builder) { builder.Append("P["); StringUtil.ToSeparatedString(builder, m_attributes, ","); builder.Append("] = "); m_rightCellQuery.ToFullString(builder); } // effects: Modifies stringBuilder to contain the view corresponding // to the right cellquery internal override void ToCompactString(StringBuilder stringBuilder) { stringBuilder.Append(OriginalCellNumberString); } // effects: Writes m_cellWrappers to builder internal static void WrappersToStringBuilder(StringBuilder builder, List wrappers, string header) { builder.AppendLine() .Append(header) .AppendLine(); // Sort them according to the original cell number LeftCellWrapper[] cellWrappers = wrappers.ToArray(); Array.Sort(cellWrappers, LeftCellWrapper.OriginalCellIdComparer); foreach (LeftCellWrapper wrapper in cellWrappers) { wrapper.ToCompactString(builder); builder.Append(" = "); wrapper.ToFullString(builder); builder.AppendLine(); } } #endregion #region Equality Comparer class // This class compares wrappers based on the Right Where Clause and // Extent -- needed for the boolean engine private class BoolWrapperComparer : IEqualityComparer { public bool Equals(LeftCellWrapper left, LeftCellWrapper right) { // Quick check with references if (object.ReferenceEquals(left, right)) { // Gets the Null and Undefined case as well return true; } // One of them is non-null at least if (left == null || right == null) { return false; } // Both are non-null at this point bool whereClauseEqual = BoolExpression.EqualityComparer.Equals(left.RightCellQuery.WhereClause, right.RightCellQuery.WhereClause); return left.RightExtent.Equals(right.RightExtent) && whereClauseEqual; } public int GetHashCode(LeftCellWrapper wrapper) { return BoolExpression.EqualityComparer.GetHashCode(wrapper.RightCellQuery.WhereClause) ^ wrapper.RightExtent.GetHashCode(); } } #endregion #region Comparer // A class that compares two cell wrappers. Useful for guiding heuristics // and to ensure that the largest selection domain (i.e., the number of // multiconstants in "mc in {...}") is first in the list private class LeftCellWrapperComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { // More attributes first -- so that we get most attributes // with very few intersections (when we use the sortings for // that). When we are subtracting, attributes are not important // Use FragmentQuery's attributes instead of LeftCellWrapper's original attributes in the comparison // since the former might have got extended to include all attributes whose value is determined // by the WHERE clause (e.g., if we have WHERE ProductName='Camera' we can assume ProductName is projected) if (x.FragmentQuery.Attributes.Count > y.FragmentQuery.Attributes.Count) { return -1; } else if (x.FragmentQuery.Attributes.Count < y.FragmentQuery.Attributes.Count) { return 1; } // Since the sort may not be stable, we use the original cell number string to break the tie return String.CompareOrdinal(x.OriginalCellNumberString, y.OriginalCellNumberString); } } // A class that compares two cell wrappers based on original cell number internal class CellIdComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { return StringComparer.Ordinal.Compare(x.OriginalCellNumberString, y.OriginalCellNumberString); } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CqlBlock.cs
- GridViewHeaderRowPresenterAutomationPeer.cs
- InputElement.cs
- HttpCacheParams.cs
- SqlDataSourceView.cs
- RSAOAEPKeyExchangeFormatter.cs
- BuilderPropertyEntry.cs
- PermissionListSet.cs
- OutputWindow.cs
- CompositeFontFamily.cs
- FormViewRow.cs
- DataObjectAttribute.cs
- HttpCookiesSection.cs
- EntityCommand.cs
- validationstate.cs
- DataRelationCollection.cs
- DeploymentExceptionMapper.cs
- TranslateTransform3D.cs
- CqlLexerHelpers.cs
- DefaultMemberAttribute.cs
- EventSourceCreationData.cs
- WpfXamlMember.cs
- StateDesignerConnector.cs
- ColorMap.cs
- Rectangle.cs
- XmlAnyElementAttributes.cs
- MergeEnumerator.cs
- HttpListenerRequestTraceRecord.cs
- SQLInt32Storage.cs
- DurableServiceAttribute.cs
- CachedFontFamily.cs
- Brush.cs
- OdbcConnectionPoolProviderInfo.cs
- ReadOnlyObservableCollection.cs
- EmitterCache.cs
- HtmlTernaryTree.cs
- TdsParserSessionPool.cs
- KeyPullup.cs
- DisplayInformation.cs
- TextBox.cs
- InputReportEventArgs.cs
- RootBrowserWindowAutomationPeer.cs
- UnsafeNativeMethodsMilCoreApi.cs
- WebCategoryAttribute.cs
- DataBindingHandlerAttribute.cs
- ComponentResourceKey.cs
- HighContrastHelper.cs
- TagMapCollection.cs
- RuleSetDialog.cs
- DateTimeParse.cs
- documentation.cs
- SerTrace.cs
- UInt16.cs
- SqlDataSourceConnectionPanel.cs
- PathGeometry.cs
- CompilerScope.cs
- AuthenticationService.cs
- StrokeSerializer.cs
- ReadOnlyCollectionBuilder.cs
- StylusPointPropertyUnit.cs
- ClientTargetCollection.cs
- XslCompiledTransform.cs
- _BufferOffsetSize.cs
- InstanceDataCollection.cs
- ValidatorCollection.cs
- Double.cs
- CommandField.cs
- ElementUtil.cs
- SettingsBindableAttribute.cs
- ActiveXHelper.cs
- SafeNativeMethodsMilCoreApi.cs
- PasswordBoxAutomationPeer.cs
- WindowsTokenRoleProvider.cs
- UserNameSecurityToken.cs
- XmlEncoding.cs
- TypeElement.cs
- TimelineGroup.cs
- Geometry.cs
- HandlerWithFactory.cs
- GenericsNotImplementedException.cs
- ClientWindowsAuthenticationMembershipProvider.cs
- PrintEvent.cs
- ToolStripContainer.cs
- DiscoveryMessageSequence.cs
- CharacterBuffer.cs
- HttpProfileGroupBase.cs
- CodeCatchClauseCollection.cs
- ByteAnimationBase.cs
- ImageListUtils.cs
- EventItfInfo.cs
- ReceiveCompletedEventArgs.cs
- SelectedCellsCollection.cs
- ToolboxItem.cs
- TextEditor.cs
- AddressAlreadyInUseException.cs
- Pair.cs
- FileDialogCustomPlace.cs
- Gdiplus.cs
- CollaborationHelperFunctions.cs
- MembershipSection.cs