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
- SqlTypesSchemaImporter.cs
- ListView.cs
- FunctionMappingTranslator.cs
- EventPrivateKey.cs
- ItemContainerProviderWrapper.cs
- OrderedHashRepartitionStream.cs
- IgnoreFlushAndCloseStream.cs
- SoapCommonClasses.cs
- New.cs
- HostSecurityManager.cs
- SkewTransform.cs
- MDIControlStrip.cs
- DeadCharTextComposition.cs
- WebResourceUtil.cs
- CharacterMetrics.cs
- PropertyConverter.cs
- EntityDataSourceEntitySetNameItem.cs
- LogicalCallContext.cs
- DiscoveryEndpoint.cs
- EntityConnectionStringBuilder.cs
- FixedSOMContainer.cs
- WinEventQueueItem.cs
- PersistChildrenAttribute.cs
- ContentElement.cs
- KeyedHashAlgorithm.cs
- DataChangedEventManager.cs
- LogoValidationException.cs
- NotImplementedException.cs
- PolicyException.cs
- PersonalizationProviderHelper.cs
- Brushes.cs
- PrintPreviewGraphics.cs
- GlobalProxySelection.cs
- CodePageEncoding.cs
- DataGridViewCellMouseEventArgs.cs
- PackWebRequest.cs
- Permission.cs
- Roles.cs
- X509ChainElement.cs
- HostingPreferredMapPath.cs
- VisualBasicHelper.cs
- DiscoveryExceptionDictionary.cs
- MessageBox.cs
- BitmapEffectInputData.cs
- IndexedString.cs
- FrameAutomationPeer.cs
- RecordsAffectedEventArgs.cs
- KeyValuePair.cs
- DesignerDataSourceView.cs
- ArrangedElementCollection.cs
- ScaleTransform.cs
- RuleSettings.cs
- FormatConvertedBitmap.cs
- TailPinnedEventArgs.cs
- EntityStoreSchemaFilterEntry.cs
- SyntaxCheck.cs
- Pkcs7Recipient.cs
- AttributeQuery.cs
- OracleMonthSpan.cs
- Utils.cs
- PasswordPropertyTextAttribute.cs
- Base64Stream.cs
- SafeCryptHandles.cs
- ButtonBaseAutomationPeer.cs
- MimeXmlImporter.cs
- EventRecord.cs
- SecurityIdentifierElementCollection.cs
- DispatcherOperation.cs
- MultiTouchSystemGestureLogic.cs
- EndGetFileNameFromUserRequest.cs
- SiteMapPath.cs
- EntitySqlQueryCacheEntry.cs
- OpenFileDialog.cs
- RoleService.cs
- WebHeaderCollection.cs
- UInt16Converter.cs
- XmlHierarchyData.cs
- ClientBuildManagerCallback.cs
- GradientBrush.cs
- TraceUtility.cs
- PagesChangedEventArgs.cs
- AssemblyResourceLoader.cs
- MetadataFile.cs
- PageBuildProvider.cs
- Transform3DGroup.cs
- DbDataReader.cs
- ModulesEntry.cs
- Style.cs
- ReadOnlyPropertyMetadata.cs
- ForceCopyBuildProvider.cs
- DBConcurrencyException.cs
- PropertyCollection.cs
- BehaviorEditorPart.cs
- ValueChangedEventManager.cs
- PrinterSettings.cs
- SessionState.cs
- X509Extension.cs
- WindowsFormsHost.cs
- PathSegmentCollection.cs
- XmlSchemaParticle.cs