Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / Validator.cs / 4 / 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
- CurrentChangingEventManager.cs
- HyperLinkStyle.cs
- FocusManager.cs
- CallSiteBinder.cs
- ConfigurationPropertyAttribute.cs
- ChildChangedEventArgs.cs
- Vector3DConverter.cs
- PerformanceCounterPermission.cs
- GregorianCalendar.cs
- TabletDevice.cs
- SemanticTag.cs
- HighContrastHelper.cs
- ToolStripItemClickedEventArgs.cs
- SoapCodeExporter.cs
- Image.cs
- WorkItem.cs
- ConnectionAcceptor.cs
- TemplateColumn.cs
- PolicyUnit.cs
- DeviceFilterEditorDialog.cs
- ProxyAttribute.cs
- ColorConvertedBitmap.cs
- PromptStyle.cs
- XmlBinaryReader.cs
- ListMarkerSourceInfo.cs
- DataGridViewCellValidatingEventArgs.cs
- CategoryAttribute.cs
- MessageQueuePermissionAttribute.cs
- MatrixIndependentAnimationStorage.cs
- XmlDocumentType.cs
- HtmlSelect.cs
- OnOperation.cs
- ResourceDescriptionAttribute.cs
- DataControlReference.cs
- SecurityTokenProvider.cs
- PingOptions.cs
- ISCIIEncoding.cs
- IntSecurity.cs
- CharacterBuffer.cs
- GridViewCellAutomationPeer.cs
- ConvertBinder.cs
- ButtonRenderer.cs
- RegexReplacement.cs
- BrowserCapabilitiesCompiler.cs
- BoundPropertyEntry.cs
- BinaryMessageEncodingBindingElement.cs
- UserInitiatedNavigationPermission.cs
- UnsafeNativeMethods.cs
- ToolboxComponentsCreatingEventArgs.cs
- DataBoundControlActionList.cs
- FixedTextView.cs
- PlatformNotSupportedException.cs
- Fonts.cs
- ContentHostHelper.cs
- Floater.cs
- CapabilitiesState.cs
- AccessDataSourceView.cs
- XmlSerializerFactory.cs
- MimeWriter.cs
- EditorPartChrome.cs
- DisplayInformation.cs
- FrameAutomationPeer.cs
- UpdatePanelTrigger.cs
- StaticFileHandler.cs
- TabControl.cs
- LabelLiteral.cs
- LogLogRecordHeader.cs
- DataView.cs
- RemotingServices.cs
- InputLanguageProfileNotifySink.cs
- DomainConstraint.cs
- HttpContext.cs
- SqlBuffer.cs
- RectangleHotSpot.cs
- UriSchemeKeyedCollection.cs
- DataGridDesigner.cs
- Partitioner.cs
- TrimSurroundingWhitespaceAttribute.cs
- DataContractSerializerMessageContractImporter.cs
- TimeIntervalCollection.cs
- ActivityCompletionCallbackWrapper.cs
- Configuration.cs
- GeneralTransform2DTo3DTo2D.cs
- Int64.cs
- PerspectiveCamera.cs
- IndicShape.cs
- GridItemCollection.cs
- InternalException.cs
- ComplexBindingPropertiesAttribute.cs
- EmptyReadOnlyDictionaryInternal.cs
- DataGridViewTextBoxColumn.cs
- HelpKeywordAttribute.cs
- GeneratedView.cs
- TextTreeObjectNode.cs
- SymbolType.cs
- oledbconnectionstring.cs
- LoginAutoFormat.cs
- SerialPinChanges.cs
- XmlSchemaAnyAttribute.cs
- SmtpFailedRecipientException.cs