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
Dictionary bindings = 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 Dictionary m_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
Dictionary bindings = 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 Dictionary m_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
- EventHandlerList.cs
- MultiPageTextView.cs
- TextCharacters.cs
- CreateDataSourceDialog.cs
- SelectionRange.cs
- SetStoryboardSpeedRatio.cs
- TextModifier.cs
- PnrpPermission.cs
- SecurityElement.cs
- TypeDescriptor.cs
- WebPartAddingEventArgs.cs
- DownloadProgressEventArgs.cs
- WpfGeneratedKnownProperties.cs
- SwitchLevelAttribute.cs
- XmlSerializerAssemblyAttribute.cs
- NullEntityWrapper.cs
- CaseInsensitiveComparer.cs
- ItemsControlAutomationPeer.cs
- CacheAxisQuery.cs
- SymLanguageVendor.cs
- WorkflowMarkupSerializationProvider.cs
- CompositeFontParser.cs
- MenuRenderer.cs
- Stackframe.cs
- ManualResetEvent.cs
- SafeSecurityHandles.cs
- ReaderOutput.cs
- AttributeQuery.cs
- HtmlListAdapter.cs
- TaskDesigner.cs
- SqlRecordBuffer.cs
- DomainConstraint.cs
- ShimAsPublicXamlType.cs
- SoapReflectionImporter.cs
- StylusButton.cs
- FontWeight.cs
- ConnectionManagementSection.cs
- InputReport.cs
- DynamicDataExtensions.cs
- Script.cs
- WorkflowInstanceProvider.cs
- ThaiBuddhistCalendar.cs
- SystemKeyConverter.cs
- MenuScrollingVisibilityConverter.cs
- RenderDataDrawingContext.cs
- LineProperties.cs
- GenericUriParser.cs
- UnsafeNativeMethods.cs
- GlyphTypeface.cs
- URI.cs
- future.cs
- DateTimeUtil.cs
- SimpleColumnProvider.cs
- EndOfStreamException.cs
- LayoutTableCell.cs
- BitmapFrameDecode.cs
- SamlAssertionDirectKeyIdentifierClause.cs
- ChangePassword.cs
- ScrollProviderWrapper.cs
- ObservableDictionary.cs
- webbrowsersite.cs
- MediaCommands.cs
- ReadWriteControlDesigner.cs
- GestureRecognizer.cs
- XmlSchemaSequence.cs
- ApplicationBuildProvider.cs
- KeyValueConfigurationElement.cs
- MethodBuilderInstantiation.cs
- CharacterMetricsDictionary.cs
- BamlStream.cs
- HttpModulesSection.cs
- ProgressChangedEventArgs.cs
- HuffCodec.cs
- DbException.cs
- initElementDictionary.cs
- PerformanceCounterPermissionAttribute.cs
- AppDomainResourcePerfCounters.cs
- Size3D.cs
- DtrList.cs
- BinaryMethodMessage.cs
- BinarySerializer.cs
- DataServiceException.cs
- ActiveDesignSurfaceEvent.cs
- Shape.cs
- FormClosingEvent.cs
- TextEditor.cs
- FixedPageStructure.cs
- StreamWithDictionary.cs
- EntityDataSourceReferenceGroup.cs
- DecimalAverageAggregationOperator.cs
- WebPartConnectionsCancelVerb.cs
- ObjectListCommandCollection.cs
- CodeNamespaceImportCollection.cs
- WebControl.cs
- HitTestParameters.cs
- XslNumber.cs
- MasterPage.cs
- remotingproxy.cs
- WorkflowTransactionService.cs
- StrokeNodeOperations2.cs