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
- TagPrefixCollection.cs
- SQLInt16Storage.cs
- UserNamePasswordValidator.cs
- SqlCommandBuilder.cs
- DataPagerCommandEventArgs.cs
- WebEventCodes.cs
- ClientSettings.cs
- NumberEdit.cs
- Column.cs
- ClientTargetSection.cs
- TypeConvertions.cs
- Knowncolors.cs
- SaveFileDialog.cs
- Keyboard.cs
- ScriptingWebServicesSectionGroup.cs
- ExpressionConverter.cs
- TraceLog.cs
- XPathMultyIterator.cs
- ImageInfo.cs
- ApplicationProxyInternal.cs
- IndexedString.cs
- PropertyGeneratedEventArgs.cs
- AtlasWeb.Designer.cs
- RuleRefElement.cs
- Wizard.cs
- MapPathBasedVirtualPathProvider.cs
- XmlDictionaryReaderQuotas.cs
- ConstructorBuilder.cs
- DBSchemaRow.cs
- BindingValueChangedEventArgs.cs
- WorkflowEventArgs.cs
- ServiceObjectContainer.cs
- CompilationLock.cs
- CompilerParameters.cs
- HttpModuleActionCollection.cs
- Vector3DAnimationUsingKeyFrames.cs
- PerformanceCounterPermissionAttribute.cs
- DesignParameter.cs
- TailCallAnalyzer.cs
- bindurihelper.cs
- PinnedBufferMemoryStream.cs
- ContentPropertyAttribute.cs
- SRGSCompiler.cs
- PackagePartCollection.cs
- smtpconnection.cs
- DNS.cs
- TextPattern.cs
- PaintValueEventArgs.cs
- BuildProviderUtils.cs
- PKCS1MaskGenerationMethod.cs
- XmlConvert.cs
- TypeBinaryExpression.cs
- Int16.cs
- Misc.cs
- XmlAttributeAttribute.cs
- ImageBrush.cs
- Timer.cs
- BamlRecordHelper.cs
- EditCommandColumn.cs
- CharAnimationBase.cs
- DesignerSerializationVisibilityAttribute.cs
- DataControlFieldHeaderCell.cs
- RouteTable.cs
- AuthorizationRuleCollection.cs
- EntitySqlQueryCacheKey.cs
- PeerNameRegistration.cs
- ConstrainedDataObject.cs
- ListBase.cs
- SystemMulticastIPAddressInformation.cs
- UriSchemeKeyedCollection.cs
- securitycriticaldataClass.cs
- KnownTypesProvider.cs
- WebPartMovingEventArgs.cs
- LinkedList.cs
- ipaddressinformationcollection.cs
- ConfigurationManagerHelperFactory.cs
- ParameterReplacerVisitor.cs
- DefinitionProperties.cs
- WebEncodingValidator.cs
- BitmapImage.cs
- StylusPointPropertyInfo.cs
- _ScatterGatherBuffers.cs
- SafeReversePInvokeHandle.cs
- HttpFileCollectionBase.cs
- EventWaitHandleSecurity.cs
- LoginView.cs
- DrawingBrush.cs
- OutputCache.cs
- PropertyValue.cs
- VarInfo.cs
- DataPointer.cs
- MimeMultiPart.cs
- SpAudioStreamWrapper.cs
- OutgoingWebResponseContext.cs
- XmlHierarchicalEnumerable.cs
- PolicyException.cs
- AdRotator.cs
- StringDictionaryCodeDomSerializer.cs
- HttpContextWrapper.cs
- QueryGeneratorBase.cs