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
- EventProxy.cs
- _LazyAsyncResult.cs
- DataGridViewColumnDesigner.cs
- ErrorInfoXmlDocument.cs
- InternalTransaction.cs
- DataStreamFromComStream.cs
- TextServicesDisplayAttributePropertyRanges.cs
- RuntimeArgumentHandle.cs
- NullableLongAverageAggregationOperator.cs
- DeobfuscatingStream.cs
- CryptoApi.cs
- FlowPosition.cs
- _NetworkingPerfCounters.cs
- SqlColumnizer.cs
- bindurihelper.cs
- XmlMapping.cs
- ValidationRuleCollection.cs
- ChannelRequirements.cs
- ExtendedProtectionPolicy.cs
- ScriptMethodAttribute.cs
- MemoryStream.cs
- PolicyLevel.cs
- NavigationCommands.cs
- WebPartVerbCollection.cs
- CompilationLock.cs
- DecoderFallback.cs
- DynamicMetaObjectBinder.cs
- PolicyChain.cs
- HelpEvent.cs
- util.cs
- OpenFileDialog.cs
- DeferredReference.cs
- PathSegmentCollection.cs
- ScriptingScriptResourceHandlerSection.cs
- StorageComplexTypeMapping.cs
- GlobalizationSection.cs
- loginstatus.cs
- ImageCreator.cs
- Sentence.cs
- Trigger.cs
- SourceFileBuildProvider.cs
- CachedResourceDictionaryExtension.cs
- HandlerWithFactory.cs
- OutputChannelBinder.cs
- WizardStepBase.cs
- SizeAnimationUsingKeyFrames.cs
- PrimarySelectionAdorner.cs
- PropertyPushdownHelper.cs
- StartFileNameEditor.cs
- IntSecurity.cs
- Double.cs
- InstallerTypeAttribute.cs
- EventsTab.cs
- CompositionCommandSet.cs
- PaperSource.cs
- ContextMenuStripActionList.cs
- Timer.cs
- WindowAutomationPeer.cs
- SymbolMethod.cs
- XmlConvert.cs
- Crc32.cs
- RootBuilder.cs
- ListViewContainer.cs
- BasePattern.cs
- SystemTcpConnection.cs
- ParsedAttributeCollection.cs
- SiteMapSection.cs
- TdsParserHelperClasses.cs
- NominalTypeEliminator.cs
- PtsPage.cs
- MarshalByValueComponent.cs
- FixedSOMFixedBlock.cs
- StoragePropertyMapping.cs
- StatusBarItemAutomationPeer.cs
- SqlWebEventProvider.cs
- ServiceContractGenerator.cs
- TimeSpanStorage.cs
- WebConfigurationFileMap.cs
- GlyphCollection.cs
- DBNull.cs
- BitmapEffectInput.cs
- KeyboardNavigation.cs
- CoTaskMemUnicodeSafeHandle.cs
- DrawingImage.cs
- TextContainerChangedEventArgs.cs
- Registry.cs
- ButtonBaseAutomationPeer.cs
- ResourceSet.cs
- HierarchicalDataTemplate.cs
- FunctionMappingTranslator.cs
- DateRangeEvent.cs
- GeometryDrawing.cs
- CapabilitiesState.cs
- NestedContainer.cs
- ServiceManager.cs
- MobilePage.cs
- ValueSerializerAttribute.cs
- CatalogZoneAutoFormat.cs
- MdiWindowListStrip.cs
- AuditLog.cs