Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / Validator.cs / 1 / Validator.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Diagnostics;
namespace System.Data.Common.CommandTrees.Internal
{
internal class Validator : BasicExpressionVisitor
{
#region Private Member Variables
private Stack> _scopes = new Stack>();
private Stack _cycleStack = new Stack();
#endregion
#region Private Implementation
private void Reset()
{
_scopes.Clear();
_cycleStack.Clear();
}
private void PushScope()
{
_scopes.Push(new Dictionary());
}
private void PopScope()
{
_scopes.Pop();
}
private void AddToScope(string strName, TypeUsage t)
{
_scopes.Peek().Add(strName, t);
}
private void AddToScope(IEnumerable> scopeElements)
{
Dictionary currentScope = _scopes.Peek();
foreach (KeyValuePair scopeElement in scopeElements)
{
currentScope.Add(scopeElement.Key, scopeElement.Value);
}
}
private TypeUsage FindInScopes(string name)
{
TypeUsage foundType = null;
foreach (Dictionary scope in _scopes)
{
if (scope.TryGetValue(name, out foundType))
{
return foundType;
}
}
return null;
}
private void Validate(DbExpression expression)
{
this.Reset();
VisitExpression(expression);
}
private static void Invalid(DbCommandTree tree, string message)
{
InvalidCommandTreeException ict = new InvalidCommandTreeException(message);
EntityUtil.TraceExceptionAsReturnValue(ict);
throw ict;
}
#endregion
#region Constructors
public Validator()
{
}
#endregion
#region 'Public' Validation API
internal void Validate(DbQueryCommandTree cmd)
{
EntityUtil.CheckArgumentNull(cmd, "cmd");
using (new EntityBid.ScopeAuto(" cmd=%d#", cmd.ObjectId))
{
if (null == cmd.Query)
{
Invalid(cmd, System.Data.Entity.Strings.Cqt_QueryTree_NullQueryInvalid);
}
this.Validate(cmd.Query);
}
}
#endregion
#region BasicExpressionVisitor IExpressionVisitor implementation overrides
public override void Visit(DbVariableReferenceExpression e)
{
TypeUsage varType = this.FindInScopes(e.VariableName);
if (null == varType)
{
Invalid(e.CommandTree, System.Data.Entity.Strings.Cqt_Validator_VarRefInvalid(e.VariableName));
}
// SQLBUDT#545720: Equivalence is not a sufficient check (consider row types) - equality is required.
if (!TypeSemantics.IsStructurallyEqualTo(e.ResultType, varType))
{
Invalid(e.CommandTree, System.Data.Entity.Strings.Cqt_Validator_VarRefTypeMismatch(e.VariableName));
}
}
public override void Visit(DbParameterReferenceExpression e)
{
if (!e.CommandTree.HasParameter(e.ParameterName, e.ResultType))
{
Invalid(e.CommandTree, System.Data.Entity.Strings.Cqt_CommandTree_NoParameterExists);
}
}
public override void Visit(DbCrossJoinExpression e)
{
//
// SQL BU Defect Tracking #422696: CQT DbJoinExpression allows left-correlation of Inputs
// Visit(DbJoinExpression) must be overriden since VisitExpressionBindingPre has been overridden to bring the DbExpressionBinding's
// variable into scope. This is not correct for DbJoinExpression since it brings each Input's variable into scope
// as it is visited, meaning that a subsequent Input can reference the variable of a preceeding Input (left correlation).
// Since left-correlation is explicitly not allowed in CQT DbJoinExpression, the correct approach is not visit the expression
// of each Input binding - not by calling VisitExpressionBindingPre - and bring the variables of all Inputs into scope
// only when the Join condition is visited. After visiting the condition, the current scope is popped from the stack
// with a call to m_scopes.Pop() rather than by calling VisitExpressionBindingPost for each Input DbExpressionBinding.
//
//
// Visit the expression of each Input binding, without updating the variables that are in scope
//
for(int idx = 0; idx < e.Inputs.Count; idx++)
{
VisitExpression(e.Inputs[idx].Expression);
}
}
public override void Visit(DbJoinExpression e)
{
//
// SQL BU Defect Tracking #422696: CQT DbJoinExpression allows left-correlation of Inputs
// Visit(DbJoinExpression) must be overriden since VisitExpressionBindingPre has been overridden to bring the DbExpressionBinding's
// variable into scope. This is not correct for DbJoinExpression since it brings each Input's variable into scope
// as it is visited, meaning that a subsequent Input can reference the variable of a preceeding Input (left correlation).
// Since left-correlation is explicitly not allowed in CQT DbJoinExpression, the correct approach is not visit the expression
// of each Input binding - not by calling VisitExpressionBindingPre - and bring the variables of all Inputs into scope
// only when the Join condition is visited. After visiting the condition, the current scope is popped from the stack
// with a call to m_scopes.Pop() rather than by calling VisitExpressionBindingPost for each Input DbExpressionBinding.
//
//
// First visit the expression of each Input binding, without updating the variables that are in scope
//
List> inputVarInfo = new List>(2);
VisitExpression(e.Left.Expression);
inputVarInfo.Add(new KeyValuePair(e.Left.VariableName, e.Left.VariableType));
VisitExpression(e.Right.Expression);
inputVarInfo.Add(new KeyValuePair(e.Right.VariableName, e.Right.VariableType));
//
// Create a new scope and introduce the variables of each Input binding
//
this.PushScope();
this.AddToScope(inputVarInfo);
//
// Visit the Join condition with the Input variables in scope
//
VisitExpression(e.JoinCondition);
//
// Remove the new scope from the scope stack
//
this.PopScope();
}
#endregion
#region BasicExpressionVisitor protected API overrides
///
/// Convenience method to visit the specified , if non-null.
///
/// The expression to visit.
/// is null
public override void VisitExpression(DbExpression expression)
{
foreach(int visitedId in _cycleStack)
{
if(visitedId == expression.ObjectId)
{
Invalid(expression.CommandTree, System.Data.Entity.Strings.Cqt_Validator_CycleDetected);
}
}
_cycleStack.Push(expression.ObjectId);
base.VisitExpression(expression);
_cycleStack.Pop();
}
protected override void VisitExpressionBindingPre(DbExpressionBinding b)
{
base.VisitExpressionBindingPre(b);
this.PushScope();
this.AddToScope(b.VariableName, b.VariableType);
}
protected override void VisitExpressionBindingPost(DbExpressionBinding b)
{
base.VisitExpressionBindingPost(b);
this.PopScope();
}
protected override void VisitGroupExpressionBindingPre(DbGroupExpressionBinding gb)
{
base.VisitGroupExpressionBindingPre(gb);
this.PushScope();
this.AddToScope(gb.VariableName, gb.VariableType);
}
protected override void VisitGroupExpressionBindingMid(DbGroupExpressionBinding gb)
{
base.VisitGroupExpressionBindingMid(gb);
this.PopScope();
this.PushScope();
this.AddToScope(gb.GroupVariableName, gb.GroupVariableType);
}
protected override void VisitGroupExpressionBindingPost(DbGroupExpressionBinding gb)
{
base.VisitGroupExpressionBindingPost(gb);
this.PopScope();
}
protected override void VisitLambdaFunctionPre(EdmFunction function, DbExpression body)
{
base.VisitLambdaFunctionPre(function, body);
this.PushScope();
foreach(FunctionParameter paramInfo in function.Parameters)
{
this.AddToScope(paramInfo.Name, paramInfo.TypeUsage);
}
}
protected override void VisitLambdaFunctionPost(EdmFunction function, DbExpression body)
{
base.VisitLambdaFunctionPost(function, body);
this.PopScope();
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Diagnostics;
namespace System.Data.Common.CommandTrees.Internal
{
internal class Validator : BasicExpressionVisitor
{
#region Private Member Variables
private Stack> _scopes = new Stack>();
private Stack _cycleStack = new Stack();
#endregion
#region Private Implementation
private void Reset()
{
_scopes.Clear();
_cycleStack.Clear();
}
private void PushScope()
{
_scopes.Push(new Dictionary());
}
private void PopScope()
{
_scopes.Pop();
}
private void AddToScope(string strName, TypeUsage t)
{
_scopes.Peek().Add(strName, t);
}
private void AddToScope(IEnumerable> scopeElements)
{
Dictionary currentScope = _scopes.Peek();
foreach (KeyValuePair scopeElement in scopeElements)
{
currentScope.Add(scopeElement.Key, scopeElement.Value);
}
}
private TypeUsage FindInScopes(string name)
{
TypeUsage foundType = null;
foreach (Dictionary scope in _scopes)
{
if (scope.TryGetValue(name, out foundType))
{
return foundType;
}
}
return null;
}
private void Validate(DbExpression expression)
{
this.Reset();
VisitExpression(expression);
}
private static void Invalid(DbCommandTree tree, string message)
{
InvalidCommandTreeException ict = new InvalidCommandTreeException(message);
EntityUtil.TraceExceptionAsReturnValue(ict);
throw ict;
}
#endregion
#region Constructors
public Validator()
{
}
#endregion
#region 'Public' Validation API
internal void Validate(DbQueryCommandTree cmd)
{
EntityUtil.CheckArgumentNull(cmd, "cmd");
using (new EntityBid.ScopeAuto(" cmd=%d#", cmd.ObjectId))
{
if (null == cmd.Query)
{
Invalid(cmd, System.Data.Entity.Strings.Cqt_QueryTree_NullQueryInvalid);
}
this.Validate(cmd.Query);
}
}
#endregion
#region BasicExpressionVisitor IExpressionVisitor implementation overrides
public override void Visit(DbVariableReferenceExpression e)
{
TypeUsage varType = this.FindInScopes(e.VariableName);
if (null == varType)
{
Invalid(e.CommandTree, System.Data.Entity.Strings.Cqt_Validator_VarRefInvalid(e.VariableName));
}
// SQLBUDT#545720: Equivalence is not a sufficient check (consider row types) - equality is required.
if (!TypeSemantics.IsStructurallyEqualTo(e.ResultType, varType))
{
Invalid(e.CommandTree, System.Data.Entity.Strings.Cqt_Validator_VarRefTypeMismatch(e.VariableName));
}
}
public override void Visit(DbParameterReferenceExpression e)
{
if (!e.CommandTree.HasParameter(e.ParameterName, e.ResultType))
{
Invalid(e.CommandTree, System.Data.Entity.Strings.Cqt_CommandTree_NoParameterExists);
}
}
public override void Visit(DbCrossJoinExpression e)
{
//
// SQL BU Defect Tracking #422696: CQT DbJoinExpression allows left-correlation of Inputs
// Visit(DbJoinExpression) must be overriden since VisitExpressionBindingPre has been overridden to bring the DbExpressionBinding's
// variable into scope. This is not correct for DbJoinExpression since it brings each Input's variable into scope
// as it is visited, meaning that a subsequent Input can reference the variable of a preceeding Input (left correlation).
// Since left-correlation is explicitly not allowed in CQT DbJoinExpression, the correct approach is not visit the expression
// of each Input binding - not by calling VisitExpressionBindingPre - and bring the variables of all Inputs into scope
// only when the Join condition is visited. After visiting the condition, the current scope is popped from the stack
// with a call to m_scopes.Pop() rather than by calling VisitExpressionBindingPost for each Input DbExpressionBinding.
//
//
// Visit the expression of each Input binding, without updating the variables that are in scope
//
for(int idx = 0; idx < e.Inputs.Count; idx++)
{
VisitExpression(e.Inputs[idx].Expression);
}
}
public override void Visit(DbJoinExpression e)
{
//
// SQL BU Defect Tracking #422696: CQT DbJoinExpression allows left-correlation of Inputs
// Visit(DbJoinExpression) must be overriden since VisitExpressionBindingPre has been overridden to bring the DbExpressionBinding's
// variable into scope. This is not correct for DbJoinExpression since it brings each Input's variable into scope
// as it is visited, meaning that a subsequent Input can reference the variable of a preceeding Input (left correlation).
// Since left-correlation is explicitly not allowed in CQT DbJoinExpression, the correct approach is not visit the expression
// of each Input binding - not by calling VisitExpressionBindingPre - and bring the variables of all Inputs into scope
// only when the Join condition is visited. After visiting the condition, the current scope is popped from the stack
// with a call to m_scopes.Pop() rather than by calling VisitExpressionBindingPost for each Input DbExpressionBinding.
//
//
// First visit the expression of each Input binding, without updating the variables that are in scope
//
List> inputVarInfo = new List>(2);
VisitExpression(e.Left.Expression);
inputVarInfo.Add(new KeyValuePair(e.Left.VariableName, e.Left.VariableType));
VisitExpression(e.Right.Expression);
inputVarInfo.Add(new KeyValuePair(e.Right.VariableName, e.Right.VariableType));
//
// Create a new scope and introduce the variables of each Input binding
//
this.PushScope();
this.AddToScope(inputVarInfo);
//
// Visit the Join condition with the Input variables in scope
//
VisitExpression(e.JoinCondition);
//
// Remove the new scope from the scope stack
//
this.PopScope();
}
#endregion
#region BasicExpressionVisitor protected API overrides
///
/// Convenience method to visit the specified , if non-null.
///
/// The expression to visit.
/// is null
public override void VisitExpression(DbExpression expression)
{
foreach(int visitedId in _cycleStack)
{
if(visitedId == expression.ObjectId)
{
Invalid(expression.CommandTree, System.Data.Entity.Strings.Cqt_Validator_CycleDetected);
}
}
_cycleStack.Push(expression.ObjectId);
base.VisitExpression(expression);
_cycleStack.Pop();
}
protected override void VisitExpressionBindingPre(DbExpressionBinding b)
{
base.VisitExpressionBindingPre(b);
this.PushScope();
this.AddToScope(b.VariableName, b.VariableType);
}
protected override void VisitExpressionBindingPost(DbExpressionBinding b)
{
base.VisitExpressionBindingPost(b);
this.PopScope();
}
protected override void VisitGroupExpressionBindingPre(DbGroupExpressionBinding gb)
{
base.VisitGroupExpressionBindingPre(gb);
this.PushScope();
this.AddToScope(gb.VariableName, gb.VariableType);
}
protected override void VisitGroupExpressionBindingMid(DbGroupExpressionBinding gb)
{
base.VisitGroupExpressionBindingMid(gb);
this.PopScope();
this.PushScope();
this.AddToScope(gb.GroupVariableName, gb.GroupVariableType);
}
protected override void VisitGroupExpressionBindingPost(DbGroupExpressionBinding gb)
{
base.VisitGroupExpressionBindingPost(gb);
this.PopScope();
}
protected override void VisitLambdaFunctionPre(EdmFunction function, DbExpression body)
{
base.VisitLambdaFunctionPre(function, body);
this.PushScope();
foreach(FunctionParameter paramInfo in function.Parameters)
{
this.AddToScope(paramInfo.Name, paramInfo.TypeUsage);
}
}
protected override void VisitLambdaFunctionPost(EdmFunction function, DbExpression body)
{
base.VisitLambdaFunctionPost(function, body);
this.PopScope();
}
#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
- BuildProvider.cs
- TrustLevelCollection.cs
- DirectoryNotFoundException.cs
- SecurityDocument.cs
- NativeMethods.cs
- NavigatorOutput.cs
- BindingCompleteEventArgs.cs
- ConfigurationSettings.cs
- ConsoleKeyInfo.cs
- LinqDataSourceView.cs
- DataGridRowAutomationPeer.cs
- WebPermission.cs
- Timeline.cs
- GeneralTransform3DGroup.cs
- DefaultBindingPropertyAttribute.cs
- ListItemParagraph.cs
- DataBindingExpressionBuilder.cs
- MultiTrigger.cs
- Hyperlink.cs
- COM2ICategorizePropertiesHandler.cs
- PageOrientation.cs
- CqlBlock.cs
- FormView.cs
- KnownTypesProvider.cs
- SevenBitStream.cs
- ProfilePropertyMetadata.cs
- LinqDataView.cs
- DataGridViewComponentPropertyGridSite.cs
- UnsafeNativeMethods.cs
- ObjectStateManagerMetadata.cs
- EdmProperty.cs
- RequestCachePolicyConverter.cs
- DetailsViewRowCollection.cs
- XmlElementAttributes.cs
- SimpleFieldTemplateUserControl.cs
- SettingsSavedEventArgs.cs
- DataContractSet.cs
- HttpStreamXmlDictionaryWriter.cs
- LogExtentCollection.cs
- TransactionManager.cs
- ParenthesizePropertyNameAttribute.cs
- Int32CAMarshaler.cs
- HandlerFactoryCache.cs
- ParallelQuery.cs
- ContainerAction.cs
- RouteItem.cs
- ErrorView.xaml.cs
- PathGradientBrush.cs
- SessionIDManager.cs
- FontStretch.cs
- WriteableBitmap.cs
- RequestQueue.cs
- BaseWebProxyFinder.cs
- ApplicationInterop.cs
- ApplicationInfo.cs
- OrderedDictionary.cs
- M3DUtil.cs
- HtmlMeta.cs
- OdbcConnectionString.cs
- GestureRecognizer.cs
- Globals.cs
- GeometryCollection.cs
- XmlName.cs
- InternalsVisibleToAttribute.cs
- IUnknownConstantAttribute.cs
- DataGridRowHeader.cs
- CommandConverter.cs
- BamlBinaryWriter.cs
- EditorZoneBase.cs
- WsdlBuildProvider.cs
- PolyLineSegmentFigureLogic.cs
- BufferAllocator.cs
- PartitionResolver.cs
- BoolExpr.cs
- XomlCompilerError.cs
- AggregateNode.cs
- BidirectionalDictionary.cs
- DelimitedListTraceListener.cs
- Repeater.cs
- SequentialUshortCollection.cs
- WebControlParameterProxy.cs
- AuthenticationSection.cs
- TextContainerChangeEventArgs.cs
- ViewKeyConstraint.cs
- PassportAuthenticationEventArgs.cs
- PrePostDescendentsWalker.cs
- FontCollection.cs
- ACE.cs
- Html32TextWriter.cs
- ButtonPopupAdapter.cs
- DesignTimeTemplateParser.cs
- DecimalConstantAttribute.cs
- TableRowsCollectionEditor.cs
- PromptEventArgs.cs
- ArraySortHelper.cs
- StrokeFIndices.cs
- DataReaderContainer.cs
- RemotingService.cs
- Math.cs
- _ShellExpression.cs