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
- safemediahandle.cs
- GridViewItemAutomationPeer.cs
- SQLBinary.cs
- ConsoleKeyInfo.cs
- SqlCacheDependencySection.cs
- ISAPIRuntime.cs
- SerializerWriterEventHandlers.cs
- AttributeXamlType.cs
- CodeStatement.cs
- EntityConnection.cs
- Stacktrace.cs
- DataGridViewCellCollection.cs
- SQLInt16.cs
- ImageButton.cs
- PropertyGridView.cs
- MouseCaptureWithinProperty.cs
- DesignerSerializationVisibilityAttribute.cs
- NonParentingControl.cs
- UIElementHelper.cs
- FormsAuthenticationEventArgs.cs
- BufferedConnection.cs
- TextDataBindingHandler.cs
- AbstractSvcMapFileLoader.cs
- BlockUIContainer.cs
- OdbcParameter.cs
- SendMailErrorEventArgs.cs
- _AutoWebProxyScriptWrapper.cs
- TableLayoutColumnStyleCollection.cs
- MinimizableAttributeTypeConverter.cs
- ToolStripProfessionalLowResolutionRenderer.cs
- TerminatorSinks.cs
- TickBar.cs
- BrushMappingModeValidation.cs
- Substitution.cs
- WSIdentityFaultException.cs
- ObjectDataSourceDisposingEventArgs.cs
- QilBinary.cs
- HttpCapabilitiesBase.cs
- ZipIOFileItemStream.cs
- EdmItemCollection.OcAssemblyCache.cs
- _FixedSizeReader.cs
- QuaternionConverter.cs
- RuntimeEnvironment.cs
- Reference.cs
- LineServicesRun.cs
- ProfileService.cs
- IdentityReference.cs
- TypeNameParser.cs
- ParameterElement.cs
- DataSpaceManager.cs
- SecurityState.cs
- ClientSession.cs
- ScriptingJsonSerializationSection.cs
- RadioButtonFlatAdapter.cs
- MethodAccessException.cs
- PermissionListSet.cs
- SchemaName.cs
- XmlArrayAttribute.cs
- XmlLanguage.cs
- DescendantBaseQuery.cs
- HtmlTableRowCollection.cs
- ErrorFormatter.cs
- WebHttpBinding.cs
- _UriTypeConverter.cs
- QueryTask.cs
- XmlTypeAttribute.cs
- PageCache.cs
- SmtpAuthenticationManager.cs
- RoleManagerSection.cs
- SqlBulkCopy.cs
- XmlUtil.cs
- PnrpPermission.cs
- PathGeometry.cs
- CollectionViewSource.cs
- MouseGesture.cs
- FontFamilyIdentifier.cs
- DrawingGroup.cs
- WhitespaceRuleReader.cs
- FileIOPermission.cs
- ExpressionVisitor.cs
- CellTreeNodeVisitors.cs
- hebrewshape.cs
- OdbcConnectionFactory.cs
- FrameworkContentElementAutomationPeer.cs
- Enlistment.cs
- CompositeFontFamily.cs
- WorkflowValidationFailedException.cs
- RowBinding.cs
- AmbiguousMatchException.cs
- StrongName.cs
- SamlAuthorizationDecisionClaimResource.cs
- DependencyObjectPropertyDescriptor.cs
- CompositeScriptReferenceEventArgs.cs
- AnimationLayer.cs
- References.cs
- IncrementalHitTester.cs
- XmlHierarchyData.cs
- HttpCacheVary.cs
- ArrayElementGridEntry.cs
- WorkflowFormatterBehavior.cs