Validator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / Validator.cs / 2 / 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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK