Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / ViewSimplifier.cs / 2 / ViewSimplifier.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.CommandTrees; using System.Collections.Generic; using System.Data.Metadata.Edm; using System.Diagnostics; using System.Data.Common.Utils; using System.Linq; using System.Globalization; namespace System.Data.Common.CommandTrees.Internal { ////// Utility class that walks a mapping view and returns a simplified expression with projection /// nodes collapsed. Specifically recognizes the following common pattern in mapping views: /// /// outerProject(outerBinding(innerProject(innerBinding, innerNew)), outerProjection) /// /// Recognizes simple disciminator patterns of the form: /// /// select /// case when Disc = value1 then value Type1(...) /// case when Disc = value2 then value Type2(...) /// ... /// /// Recognizes redundant case statement of the form: /// /// select /// case when (case when Predicate1 then true else false) ... /// /// internal static class ViewSimplifier { internal static DbQueryCommandTree SimplifyView(DbQueryCommandTree view) { view = view.Clone(); view.Replace(CollapseProject); view.Replace(SimplifyCaseStatements); return view; } ////// This expression replacer delegate supports collapsing a nested projection matching the pattern described above. /// /// For instance: /// /// select T.a as x, T.b as y, true as z from (select E.a as x, E.b as y from Extent E) /// /// resolves to: /// /// select E.a, E.b, true as z from Extent E /// /// In general, /// /// outerProject( /// outerBinding( /// innerProject(innerBinding, innerNew) /// ), /// outerNew) /// /// resolves to: /// /// replacementOuterProject( /// innerBinding, /// replacementOuterNew) /// /// The outer projection is bound to the inner input source (outerBinding -> innerBinding) and /// the outer new instance expression has its properties remapped to the inner new instance /// expression member expressions. /// private static void CollapseProject(ExpressionReplacement replacement) { // retrieve the replacement candidate DbExpression candidate = replacement.Current; DbProjectExpression outerProject; DbExpression outerProjection; DbProjectExpression innerProject; DbNewInstanceExpression innerNew; // determine if the candidate matches the pattern we know how to rewrite if (TryMatchNestedProjectPattern(candidate, out outerProject, out outerProjection, out innerProject, out innerNew)) { CollapseNestedProjection(replacement, outerProject, outerProjection, innerProject, innerNew); } } ////// determines if an expression is of the form outerProject(outerProjection(innerProject(innerNew))), /// returning these elements /// private static bool TryMatchNestedProjectPattern(DbExpression outerCandidate, out DbProjectExpression outerProject, out DbExpression outerProjection, out DbProjectExpression innerProject, out DbNewInstanceExpression innerNew) { // init output parameters outerProject = null; outerProjection = null; innerProject = null; innerNew = null; // check the pattern if (outerCandidate.ExpressionKind != DbExpressionKind.Project) { return false; } outerProject = (DbProjectExpression)outerCandidate; outerProjection = outerProject.Projection; if (outerProject.Input.Expression.ExpressionKind != DbExpressionKind.Project) { return false; } innerProject = (DbProjectExpression)outerProject.Input.Expression; if (innerProject.Projection.ExpressionKind != DbExpressionKind.NewInstance) { return false; } innerNew = (DbNewInstanceExpression)innerProject.Projection; return true; } ////// Collapses outerProject(outerProjection(innerProject(innerNew))) /// private static void CollapseNestedProjection(ExpressionReplacement replacement, DbProjectExpression outerProject, DbExpression outerProjection, DbProjectExpression innerProject, DbNewInstanceExpression innerNew) { replacement.VisitReplacement = true; // continue collapsing projection until the pattern no longer matches // get membername -> expression bindings for the inner select so that we know how map property // references to the inner projectio Dictionarybindings = new Dictionary (innerNew.Arguments.Count); TypeUsage innerResultTypeUsage = innerNew.ResultType; RowType innerResultType = (RowType)innerResultTypeUsage.EdmType; for (int ordinal = 0; ordinal < innerResultType.Members.Count; ordinal++) { bindings[innerResultType.Members[ordinal].Name] = innerNew.Arguments[ordinal]; } // initialize an expression replacer that knows how to map arguments to the outer projection // to the inner projection source ProjectionCollapser collapser = new ProjectionCollapser(bindings, outerProject.Input); ExpressionReplacer replacer = new ExpressionReplacer(collapser.CollapseProjection); // replace all property references to the inner projection var replacementOuterProjection = replacer.Replace(outerProjection); DbProjectExpression replacementOuterProject = outerProject.CommandTree.CreateProjectExpression( innerProject.Input, replacementOuterProjection); // make sure the collapsing was successful; if not, give up on simplification if (collapser.IsDoomed) { return; } // set replacement value so that the expression replacer infrastructure can substitute // the collapsed projection in the expression tree replacement.Replacement = replacementOuterProject; } private static void SimplifyCaseStatements(ExpressionReplacement replacement) { var candidate = replacement.Current; if (candidate.ExpressionKind != DbExpressionKind.Case) { return; } var caseExpression = (DbCaseExpression)replacement.Current; // try simplifying predicates bool predicateSimplified = false; List rewrittenPredicates = new List (caseExpression.When.Count); foreach (var when in caseExpression.When) { DbExpression simplifiedPredicate; if (TrySimplifyPredicate(when, out simplifiedPredicate)) { rewrittenPredicates.Add(simplifiedPredicate); predicateSimplified = true; } else { rewrittenPredicates.Add(when); } } if (!predicateSimplified) { return; } replacement.Replacement = caseExpression.CommandTree.CreateCaseExpression( rewrittenPredicates, caseExpression.Then, caseExpression.Else); replacement.VisitReplacement = true; } private static bool TrySimplifyPredicate(DbExpression predicate, out DbExpression simplified) { simplified = null; if (predicate.ExpressionKind != DbExpressionKind.Case) { return false; } var caseExpression = (DbCaseExpression)predicate; if (caseExpression.Then.Count != 1 && caseExpression.Then[0].ExpressionKind == DbExpressionKind.Constant) { return false; } var then = (DbConstantExpression)caseExpression.Then[0]; if (!true.Equals(then.Value)) { return false; } if (caseExpression.Else != null) { if (caseExpression.Else.ExpressionKind != DbExpressionKind.Constant) { return false; } var when = (DbConstantExpression)caseExpression.Else; if (!false.Equals(when.Value)) { return false; } } simplified = caseExpression.When[0]; return true; } /// /// replacer used to simplify argument value in a new instance expression OuterNew from /// an expression of the form: /// /// outerProject(outerBinding(innerProject(innerBinding, innerNew)), outerProjection) /// /// The replacer collapses the outer project terms to point at the innerNew expression. /// Where possible, VarRef_outer.Property_outer is collapsed to VarRef_inner.Property. /// private class ProjectionCollapser { // the replacer context keeps track of member bindings for var refs and the expression // binding for the outer projection being remapped private Dictionarym_varRefMemberBindings; private DbExpressionBinding m_outerBinding; private bool m_doomed; internal ProjectionCollapser(Dictionary varRefMemberBindings, DbExpressionBinding outerBinding) { m_varRefMemberBindings = varRefMemberBindings; m_outerBinding = outerBinding; } // replacer delegate that identifies the Property(VarRef "Outer binding") pattern, // and remaps the property to the appropriate inner projection member internal void CollapseProjection(ExpressionReplacement replacement) { // check for a property of the outer projection binding (that can be remapped) if (replacement.Current.ExpressionKind == DbExpressionKind.Property) { var property = (DbPropertyExpression)replacement.Current; if (property.Instance.ExpressionKind == DbExpressionKind.VariableReference && IsOuterBindingVarRef((DbVariableReferenceExpression)property.Instance)) { replacement.VisitReplacement = false; replacement.Replacement = m_varRefMemberBindings[property.Property.Name]; } } else if (replacement.Current.ExpressionKind == DbExpressionKind.VariableReference) { // if we encounter an unsubstitutued var ref, give up... var varRef = (DbVariableReferenceExpression)replacement.Current; if (IsOuterBindingVarRef(varRef)) { m_doomed = true; } } } /// /// Heuristic check to make sure the var ref is the one we're supposed to be replacing. /// private bool IsOuterBindingVarRef(DbVariableReferenceExpression varRef) { return varRef.VariableName == m_outerBinding.VariableName; } ////// Returns a value indicating that the transformation has failed. /// internal bool IsDoomed { get { return m_doomed; } } } /* private abstract class DiscriminatorValueCollection { ////// Add a new discriminator value. Returns true if the value is unique. /// internal abstract bool TryAddDiscriminatorValue(object value); ////// Associate a discriminator value with the given type. Returns true if the value is known. /// internal abstract bool TryAddDiscriminatorValueAssignment(object value, EntityType entityType); ////// /// internal abstract bool TryAssignDefaultType(EntityType entityType); private class TypedDiscriminatorValueCollection{ private readonly TryConvert _convert; private readonly Func , T> _generateUniqueDiscriminator; private readonly HashSet _discriminatorValues; private readonly Dictionary _discriminatorAssignments; } private delegate bool TryConvert (object input, out T output); } * */ } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.CommandTrees; using System.Collections.Generic; using System.Data.Metadata.Edm; using System.Diagnostics; using System.Data.Common.Utils; using System.Linq; using System.Globalization; namespace System.Data.Common.CommandTrees.Internal { ////// Utility class that walks a mapping view and returns a simplified expression with projection /// nodes collapsed. Specifically recognizes the following common pattern in mapping views: /// /// outerProject(outerBinding(innerProject(innerBinding, innerNew)), outerProjection) /// /// Recognizes simple disciminator patterns of the form: /// /// select /// case when Disc = value1 then value Type1(...) /// case when Disc = value2 then value Type2(...) /// ... /// /// Recognizes redundant case statement of the form: /// /// select /// case when (case when Predicate1 then true else false) ... /// /// internal static class ViewSimplifier { internal static DbQueryCommandTree SimplifyView(DbQueryCommandTree view) { view = view.Clone(); view.Replace(CollapseProject); view.Replace(SimplifyCaseStatements); return view; } ////// This expression replacer delegate supports collapsing a nested projection matching the pattern described above. /// /// For instance: /// /// select T.a as x, T.b as y, true as z from (select E.a as x, E.b as y from Extent E) /// /// resolves to: /// /// select E.a, E.b, true as z from Extent E /// /// In general, /// /// outerProject( /// outerBinding( /// innerProject(innerBinding, innerNew) /// ), /// outerNew) /// /// resolves to: /// /// replacementOuterProject( /// innerBinding, /// replacementOuterNew) /// /// The outer projection is bound to the inner input source (outerBinding -> innerBinding) and /// the outer new instance expression has its properties remapped to the inner new instance /// expression member expressions. /// private static void CollapseProject(ExpressionReplacement replacement) { // retrieve the replacement candidate DbExpression candidate = replacement.Current; DbProjectExpression outerProject; DbExpression outerProjection; DbProjectExpression innerProject; DbNewInstanceExpression innerNew; // determine if the candidate matches the pattern we know how to rewrite if (TryMatchNestedProjectPattern(candidate, out outerProject, out outerProjection, out innerProject, out innerNew)) { CollapseNestedProjection(replacement, outerProject, outerProjection, innerProject, innerNew); } } ////// determines if an expression is of the form outerProject(outerProjection(innerProject(innerNew))), /// returning these elements /// private static bool TryMatchNestedProjectPattern(DbExpression outerCandidate, out DbProjectExpression outerProject, out DbExpression outerProjection, out DbProjectExpression innerProject, out DbNewInstanceExpression innerNew) { // init output parameters outerProject = null; outerProjection = null; innerProject = null; innerNew = null; // check the pattern if (outerCandidate.ExpressionKind != DbExpressionKind.Project) { return false; } outerProject = (DbProjectExpression)outerCandidate; outerProjection = outerProject.Projection; if (outerProject.Input.Expression.ExpressionKind != DbExpressionKind.Project) { return false; } innerProject = (DbProjectExpression)outerProject.Input.Expression; if (innerProject.Projection.ExpressionKind != DbExpressionKind.NewInstance) { return false; } innerNew = (DbNewInstanceExpression)innerProject.Projection; return true; } ////// Collapses outerProject(outerProjection(innerProject(innerNew))) /// private static void CollapseNestedProjection(ExpressionReplacement replacement, DbProjectExpression outerProject, DbExpression outerProjection, DbProjectExpression innerProject, DbNewInstanceExpression innerNew) { replacement.VisitReplacement = true; // continue collapsing projection until the pattern no longer matches // get membername -> expression bindings for the inner select so that we know how map property // references to the inner projectio Dictionarybindings = new Dictionary (innerNew.Arguments.Count); TypeUsage innerResultTypeUsage = innerNew.ResultType; RowType innerResultType = (RowType)innerResultTypeUsage.EdmType; for (int ordinal = 0; ordinal < innerResultType.Members.Count; ordinal++) { bindings[innerResultType.Members[ordinal].Name] = innerNew.Arguments[ordinal]; } // initialize an expression replacer that knows how to map arguments to the outer projection // to the inner projection source ProjectionCollapser collapser = new ProjectionCollapser(bindings, outerProject.Input); ExpressionReplacer replacer = new ExpressionReplacer(collapser.CollapseProjection); // replace all property references to the inner projection var replacementOuterProjection = replacer.Replace(outerProjection); DbProjectExpression replacementOuterProject = outerProject.CommandTree.CreateProjectExpression( innerProject.Input, replacementOuterProjection); // make sure the collapsing was successful; if not, give up on simplification if (collapser.IsDoomed) { return; } // set replacement value so that the expression replacer infrastructure can substitute // the collapsed projection in the expression tree replacement.Replacement = replacementOuterProject; } private static void SimplifyCaseStatements(ExpressionReplacement replacement) { var candidate = replacement.Current; if (candidate.ExpressionKind != DbExpressionKind.Case) { return; } var caseExpression = (DbCaseExpression)replacement.Current; // try simplifying predicates bool predicateSimplified = false; List rewrittenPredicates = new List (caseExpression.When.Count); foreach (var when in caseExpression.When) { DbExpression simplifiedPredicate; if (TrySimplifyPredicate(when, out simplifiedPredicate)) { rewrittenPredicates.Add(simplifiedPredicate); predicateSimplified = true; } else { rewrittenPredicates.Add(when); } } if (!predicateSimplified) { return; } replacement.Replacement = caseExpression.CommandTree.CreateCaseExpression( rewrittenPredicates, caseExpression.Then, caseExpression.Else); replacement.VisitReplacement = true; } private static bool TrySimplifyPredicate(DbExpression predicate, out DbExpression simplified) { simplified = null; if (predicate.ExpressionKind != DbExpressionKind.Case) { return false; } var caseExpression = (DbCaseExpression)predicate; if (caseExpression.Then.Count != 1 && caseExpression.Then[0].ExpressionKind == DbExpressionKind.Constant) { return false; } var then = (DbConstantExpression)caseExpression.Then[0]; if (!true.Equals(then.Value)) { return false; } if (caseExpression.Else != null) { if (caseExpression.Else.ExpressionKind != DbExpressionKind.Constant) { return false; } var when = (DbConstantExpression)caseExpression.Else; if (!false.Equals(when.Value)) { return false; } } simplified = caseExpression.When[0]; return true; } /// /// replacer used to simplify argument value in a new instance expression OuterNew from /// an expression of the form: /// /// outerProject(outerBinding(innerProject(innerBinding, innerNew)), outerProjection) /// /// The replacer collapses the outer project terms to point at the innerNew expression. /// Where possible, VarRef_outer.Property_outer is collapsed to VarRef_inner.Property. /// private class ProjectionCollapser { // the replacer context keeps track of member bindings for var refs and the expression // binding for the outer projection being remapped private Dictionarym_varRefMemberBindings; private DbExpressionBinding m_outerBinding; private bool m_doomed; internal ProjectionCollapser(Dictionary varRefMemberBindings, DbExpressionBinding outerBinding) { m_varRefMemberBindings = varRefMemberBindings; m_outerBinding = outerBinding; } // replacer delegate that identifies the Property(VarRef "Outer binding") pattern, // and remaps the property to the appropriate inner projection member internal void CollapseProjection(ExpressionReplacement replacement) { // check for a property of the outer projection binding (that can be remapped) if (replacement.Current.ExpressionKind == DbExpressionKind.Property) { var property = (DbPropertyExpression)replacement.Current; if (property.Instance.ExpressionKind == DbExpressionKind.VariableReference && IsOuterBindingVarRef((DbVariableReferenceExpression)property.Instance)) { replacement.VisitReplacement = false; replacement.Replacement = m_varRefMemberBindings[property.Property.Name]; } } else if (replacement.Current.ExpressionKind == DbExpressionKind.VariableReference) { // if we encounter an unsubstitutued var ref, give up... var varRef = (DbVariableReferenceExpression)replacement.Current; if (IsOuterBindingVarRef(varRef)) { m_doomed = true; } } } /// /// Heuristic check to make sure the var ref is the one we're supposed to be replacing. /// private bool IsOuterBindingVarRef(DbVariableReferenceExpression varRef) { return varRef.VariableName == m_outerBinding.VariableName; } ////// Returns a value indicating that the transformation has failed. /// internal bool IsDoomed { get { return m_doomed; } } } /* private abstract class DiscriminatorValueCollection { ////// Add a new discriminator value. Returns true if the value is unique. /// internal abstract bool TryAddDiscriminatorValue(object value); ////// Associate a discriminator value with the given type. Returns true if the value is known. /// internal abstract bool TryAddDiscriminatorValueAssignment(object value, EntityType entityType); ////// /// internal abstract bool TryAssignDefaultType(EntityType entityType); private class TypedDiscriminatorValueCollection{ private readonly TryConvert _convert; private readonly Func , T> _generateUniqueDiscriminator; private readonly HashSet _discriminatorValues; private readonly Dictionary _discriminatorAssignments; } private delegate bool TryConvert (object input, out T output); } * */ } } // 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
- AdRotator.cs
- TypedRowHandler.cs
- EdgeProfileValidation.cs
- SafeTimerHandle.cs
- NullableDoubleAverageAggregationOperator.cs
- PersonalizablePropertyEntry.cs
- XsdValidatingReader.cs
- HttpSocketManager.cs
- AsymmetricCryptoHandle.cs
- ProcessModule.cs
- indexingfiltermarshaler.cs
- ChannelSinkStacks.cs
- Pair.cs
- ProfilePropertyNameValidator.cs
- EntityParameter.cs
- ActivityCollectionMarkupSerializer.cs
- MarkupExtensionReturnTypeAttribute.cs
- Mapping.cs
- DoubleSumAggregationOperator.cs
- AuthenticationModulesSection.cs
- EdgeModeValidation.cs
- Permission.cs
- FlowSwitchDesigner.xaml.cs
- HttpServerVarsCollection.cs
- TextBreakpoint.cs
- CommonObjectSecurity.cs
- SizeChangedEventArgs.cs
- ProfileGroupSettings.cs
- PersonalizablePropertyEntry.cs
- MetadataUtil.cs
- SqlTypesSchemaImporter.cs
- CommandDesigner.cs
- HelloOperationAsyncResult.cs
- SqlTypeSystemProvider.cs
- ValueUnavailableException.cs
- SqlStream.cs
- CollectionExtensions.cs
- WebUtil.cs
- FocusWithinProperty.cs
- DetailsViewPagerRow.cs
- DiscriminatorMap.cs
- MetaChildrenColumn.cs
- TrackingStringDictionary.cs
- CustomExpression.cs
- ConditionCollection.cs
- TargetException.cs
- ProfileProvider.cs
- CollectionType.cs
- FreezableDefaultValueFactory.cs
- SHA512.cs
- TableCellCollection.cs
- DoubleConverter.cs
- BeginCreateSecurityTokenRequest.cs
- ErrorHandler.cs
- CompoundFileReference.cs
- FtpRequestCacheValidator.cs
- wgx_commands.cs
- BitConverter.cs
- SmiXetterAccessMap.cs
- TableAdapterManagerHelper.cs
- CryptoProvider.cs
- XhtmlConformanceSection.cs
- DescendantOverDescendantQuery.cs
- InvalidateEvent.cs
- DesignerOptionService.cs
- CommandConverter.cs
- MetadataArtifactLoaderCompositeResource.cs
- XmlByteStreamWriter.cs
- DataException.cs
- TableLayoutColumnStyleCollection.cs
- ItemCheckEvent.cs
- ComponentSerializationService.cs
- ProtocolsConfigurationEntry.cs
- ParentQuery.cs
- DataKeyCollection.cs
- GCHandleCookieTable.cs
- Overlapped.cs
- DesignerOptionService.cs
- DataSet.cs
- WebBrowserEvent.cs
- DebugTrace.cs
- AuthStoreRoleProvider.cs
- CustomErrorCollection.cs
- DrawingServices.cs
- TimelineGroup.cs
- XmlObjectSerializer.cs
- Deserializer.cs
- EventSinkHelperWriter.cs
- CustomLineCap.cs
- ByteFacetDescriptionElement.cs
- PropertySourceInfo.cs
- FullTrustAssembly.cs
- HttpCachePolicy.cs
- DateTimeConstantAttribute.cs
- MobileComponentEditorPage.cs
- GacUtil.cs
- InfoCardRSAPKCS1SignatureFormatter.cs
- ErrorFormatterPage.cs
- ObjectReaderCompiler.cs
- _DomainName.cs