SemanticAnalyzer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / EntitySql / SemanticAnalyzer.cs / 1305376 / SemanticAnalyzer.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

namespace System.Data.Common.EntitySql 
{
    using System;
    using System.Globalization;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Linq; 
 
    using System.Data.Common.CommandTrees;
    using System.Data.Common.CommandTrees.ExpressionBuilder; 
    using System.Data.Metadata.Edm;
    using System.Data.Entity;

    ///  
    /// Implements Semantic Analysis and Conversion
    /// Provides the translation service between an abstract syntax tree to a canonical command tree 
    /// For complete documentation of the language syntax and semantics, refer to http://sqlweb/default.asp?specDirId=764 
    /// The class was designed to be type system agnostic by delegating to a given SemanticResolver instance all type related services as well as to TypeHelper class, however
    /// we rely on the assumption that metadata was pre-loaded and is relevant to the query. 
    /// 
    internal sealed class SemanticAnalyzer
    {
        private SemanticResolver _sr; 

        ///  
        /// Initializes semantic analyzer 
        /// 
        /// initialized SemanticResolver instance for a given typespace/type system 
        internal SemanticAnalyzer(SemanticResolver sr)
        {
            Debug.Assert(sr != null, "sr must not be null");
            _sr = sr; 
        }
 
        ///  
        /// Entry point to semantic analysis. Converts AST into a .
        ///  
        /// ast command tree
        /// 
        /// Thrown when Syntatic or Semantic rules are violated and the query cannot be accepted
        /// Thrown when metadata related service requests fail 
        /// Thrown when mapping related service requests fail
        ///  
        /// DbCommandTree 
        internal DbCommandTree AnalyzeCommand(AST.Node astExpr)
        { 
            //
            // Ensure that the AST expression is a valid Command expression
            //
            AST.Command astCommandExpr = ValidateQueryCommandAst(astExpr); 

            // 
            // Convert namespace imports and add them to _sr.TypeResolver. 
            //
            ConvertAndRegisterNamespaceImports(astCommandExpr.NamespaceImportList, astCommandExpr.ErrCtx, _sr); 

            //
            // Convert the AST command root expression to a command tree using the appropriate converter
            // 
            DbCommandTree commandTree = ConvertStatement(astCommandExpr.Statement, _sr);
 
            Debug.Assert(commandTree != null, "ConvertStatement returned null"); 

            return commandTree; 
        }

        /// 
        /// Converts query command AST into a . 
        /// 
        /// ast command tree 
        ///  
        /// Thrown when Syntatic or Semantic rules are violated and the query cannot be accepted
        /// Thrown when metadata related service requests fail 
        /// Thrown when mapping related service requests fail
        /// 
        /// DbExpression
        internal DbLambda AnalyzeQueryCommand(AST.Node astExpr) 
        {
            // 
            // Ensure that the AST expression is a valid query command expression 
            // (only a query command root expression can produce a standalone DbExpression)
            // 
            AST.Command astQueryCommandExpr = ValidateQueryCommandAst(astExpr);

            //
            // Convert namespace imports and add them to _sr.TypeResolver. 
            //
            ConvertAndRegisterNamespaceImports(astQueryCommandExpr.NamespaceImportList, astQueryCommandExpr.ErrCtx, _sr); 
 
            //
            // Convert the AST of the query command root expression into a DbExpression 
            //
            DbExpression expression = ConvertQueryStatementToDbExpression(astQueryCommandExpr.Statement, _sr);

            // Construct DbLambda from free variables and the expression 
            DbLambda lambda = DbExpressionBuilder.Lambda(expression, _sr.Variables.Values);
 
            Debug.Assert(lambda != null, "AnalyzeQueryCommand returned null"); 

            return lambda; 
        }

        private AST.Command ValidateQueryCommandAst(AST.Node astExpr)
        { 
            AST.Command astCommandExpr = astExpr as AST.Command;
            if (null == astCommandExpr) 
            { 
                throw EntityUtil.Argument(Strings.UnknownAstCommandExpression);
            } 

            if (!(astCommandExpr.Statement is AST.QueryStatement))
                throw EntityUtil.Argument(Strings.UnknownAstExpressionType);
 
            return astCommandExpr;
        } 
 
        /// 
        /// Converts namespace imports and adds them to the type resolver. 
        /// 
        private static void ConvertAndRegisterNamespaceImports(AST.NodeList nsImportList, ErrorContext cmdErrCtx, SemanticResolver sr)
        {
            List> aliasedNamespaceImports = new List>(); 
            List> namespaceImports = new List>();
 
            // 
            // Resolve all user-defined namespace imports to MetadataMember objects _before_ adding them to the type resolver,
            // this is needed to keep resolution within the command prolog unaffected by previously resolved imports. 
            //
            if (nsImportList != null)
            {
                foreach (AST.NamespaceImport namespaceImport in nsImportList) 
                {
                    string[] name = null; 
 
                    AST.Identifier identifier = namespaceImport.NamespaceName as AST.Identifier;
                    if (identifier != null) 
                    {
                        name = new string[] { identifier.Name };
                    }
 
                    AST.DotExpr dotExpr = namespaceImport.NamespaceName as AST.DotExpr;
                    if (dotExpr != null && dotExpr.IsMultipartIdentifier(out name)) 
                    { 
                        Debug.Assert(name != null, "name != null");
                    } 

                    if (name == null)
                    {
                        throw EntityUtil.EntitySqlError(namespaceImport.NamespaceName.ErrCtx, Strings.InvalidMetadataMemberName); 
                    }
 
                    string alias = namespaceImport.Alias != null ? namespaceImport.Alias.Name : null; 

                    MetadataMember metadataMember = sr.ResolveMetadataMemberName(name, namespaceImport.NamespaceName.ErrCtx); 
                    Debug.Assert(metadataMember != null, "metadata member name resolution must not return null");

                    if (metadataMember.MetadataMemberClass == MetadataMemberClass.Namespace)
                    { 
                        if (alias != null)
                        { 
                            aliasedNamespaceImports.Add(Tuple.Create(alias, (MetadataNamespace)metadataMember, namespaceImport.ErrCtx)); 
                        }
                        else 
                        {
                            namespaceImports.Add(Tuple.Create((MetadataNamespace)metadataMember, namespaceImport.ErrCtx));
                        }
                    } 
                    else
                    { 
                        throw EntityUtil.EntitySqlError(namespaceImport.NamespaceName.ErrCtx, Strings.InvalidMetadataMemberClassResolution( 
                            metadataMember.Name, metadataMember.MetadataMemberClassName, MetadataNamespace.NamespaceClassName));
                    } 
                }
            }

            // 
            // Add resolved user-defined imports to the type resolver.
            // Before adding user-defined namespace imports, add EDM namespace import to make canonical functions and types available in the command text. 
            // 
            sr.TypeResolver.AddNamespaceImport(new MetadataNamespace(EdmConstants.EdmNamespace), nsImportList != null ? nsImportList.ErrCtx : cmdErrCtx);
            foreach (var resolvedAliasedNamespaceImport in aliasedNamespaceImports) 
            {
                sr.TypeResolver.AddAliasedNamespaceImport(resolvedAliasedNamespaceImport.Item1, resolvedAliasedNamespaceImport.Item2, resolvedAliasedNamespaceImport.Item3);
            }
            foreach (var resolvedNamespaceImport in namespaceImports) 
            {
                sr.TypeResolver.AddNamespaceImport(resolvedNamespaceImport.Item1, resolvedNamespaceImport.Item2); 
            } 
        }
 
        /// 
        /// Dispatches/Converts statement expressions.
        /// 
        ///  
        /// SemanticResolver instance relative to a especif typespace/system
        ///  
        private static DbCommandTree ConvertStatement(AST.Statement astStatement, SemanticResolver sr) 
        {
            Debug.Assert(astStatement != null, "astStatement must not be null"); 

            StatementConverter statementConverter;
            if (astStatement is AST.QueryStatement)
            { 
                statementConverter = new StatementConverter(ConvertQueryStatementToDbCommandTree);
            } 
            else 
            {
                throw EntityUtil.Argument(Strings.UnknownAstExpressionType); 
            }

            DbCommandTree converted = statementConverter(astStatement, sr);
 
            Debug.Assert(converted != null, "statementConverter returned null");
 
            return converted; 
        }
        private delegate DbCommandTree StatementConverter(AST.Statement astExpr, SemanticResolver sr); 

        /// 
        /// Converts query statement AST to a 
        ///  
        /// SemanticResolver instance relative to a especif typespace/system
        private static DbQueryCommandTree ConvertQueryStatementToDbCommandTree(AST.Statement astStatement, SemanticResolver sr) 
        { 
            Debug.Assert(astStatement != null, "astStatement must not be null");
 
            DbExpression converted = ConvertQueryStatementToDbExpression(astStatement, sr);

            Debug.Assert(converted != null, "ConvertQueryStatementToDbExpression returned null");
 
            return DbQueryCommandTree.FromValidExpression(sr.TypeResolver.Perspective.MetadataWorkspace,
                                                          sr.TypeResolver.Perspective.TargetDataspace, 
                                                          converted); 
        }
 
        /// 
        /// Converts the query statement to a normalized and validated .
        /// This entry point to the semantic analysis phase is used when producing a
        /// query command tree or producing only a . 
        /// 
        /// The query statement 
        /// The instance to use 
        /// 
        ///     An instance of , adjusted to handle 'inline' projections 
        ///     and validated to produce a result type appropriate for the root of a query command tree.
        /// 
        private static DbExpression ConvertQueryStatementToDbExpression(AST.Statement astStatement, SemanticResolver sr)
        { 
            Debug.Assert(astStatement != null, "astStatement must not be null");
 
            AST.QueryStatement queryStatement = astStatement as AST.QueryStatement; 

            if (queryStatement == null) 
            {
                throw EntityUtil.Argument(Strings.UnknownAstExpressionType);
            }
 
            //
            // Convert query inline definitions. Converted inline definitions are added to the semantic resolver. 
            // 
            ConvertInlineFunctionDefinitions(queryStatement.FunctionDefList, sr);
 
            //
            // Convert top level expression
            //
            DbExpression converted = ConvertValueExpression(queryStatement.Expr, sr); 

            // 
            // Ensure converted expression is not untyped null. 
            // Use error context of the top-level expression.
            // 
            if (TypeSemantics.IsNullType(converted.ResultType))
            {
                throw EntityUtil.EntitySqlError(queryStatement.Expr.ErrCtx, Strings.ResultingExpressionTypeCannotBeNull);
            } 

            // 
            // Handle the "inline" projection case 
            //
            if (converted is DbScanExpression) 
            {
                DbExpressionBinding source = converted.BindAs(sr.GenerateInternalName("extent"));

                converted = source.Project(source.Variable); 
            }
 
            // 
            // Ensure return type is valid for query. For V1, association types are the only
            // type that cannot be at 'top' level result. Note that this is only applicable in 
            // general queries and association types are valid in view gen mode queries.
            // Use error context of the top-level expression.
            //
            if (sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.NormalMode) 
            {
                ValidateQueryResultType(converted.ResultType, queryStatement.Expr.ErrCtx); 
            } 

            Debug.Assert(null != converted, "null != converted"); 

            return converted;
        }
 
        /// 
        /// Ensures that the result of a query expression is valid. 
        ///  
        private static void ValidateQueryResultType(TypeUsage resultType, ErrorContext errCtx)
        { 
            if (Helper.IsCollectionType(resultType.EdmType))
            {
                ValidateQueryResultType(((CollectionType)resultType.EdmType).TypeUsage, errCtx);
            } 
            else if (Helper.IsRowType(resultType.EdmType))
            { 
                foreach (EdmProperty property in ((RowType)resultType.EdmType).Properties) 
                {
                    ValidateQueryResultType(property.TypeUsage, errCtx); 
                }
            }
            else if (Helper.IsAssociationType(resultType.EdmType))
            { 
                throw EntityUtil.EntitySqlError(errCtx, Strings.InvalidQueryResultType(resultType.Identity));
            } 
        } 

 
        /// 
        /// Converts query inline function defintions. Returns empty list in case of no definitions.
        /// 
        private static void ConvertInlineFunctionDefinitions(AST.NodeList functionDefList, SemanticResolver sr) 
        {
            if (functionDefList != null) 
            { 
                //
                // Process inline function signatures, declare functions in the type resolver. 
                //
                List inlineFunctionInfos = new List();
                foreach (AST.FunctionDefinition functionDefAst in functionDefList)
                { 
                    //
                    // Get and validate function name. 
                    // 
                    string name = functionDefAst.Name;
                    Debug.Assert(!String.IsNullOrEmpty(name), "function name must not be null or empty"); 

                    //
                    // Process function parameters
                    // 
                    List parameters = ConvertInlineFunctionParameterDefs(functionDefAst.Parameters, sr);
                    Debug.Assert(parameters != null, "parameters must not be null"); // should be empty collection if no parameters 
 
                    //
                    // Register new function in the type resolver. 
                    //
                    InlineFunctionInfo functionInfo = new InlineFunctionInfoImpl(functionDefAst, parameters);
                    inlineFunctionInfos.Add(functionInfo);
                    sr.TypeResolver.DeclareInlineFunction(name, functionInfo); 
                }
                Debug.Assert(functionDefList.Count == inlineFunctionInfos.Count); 
 
                //
                // Force validation of function recursion. 
                //
                foreach (InlineFunctionInfo functionInfo in inlineFunctionInfos)
                {
                    functionInfo.GetLambda(sr); 
                }
            } 
        } 

        private static List ConvertInlineFunctionParameterDefs(AST.NodeList parameterDefs, SemanticResolver sr) 
        {
            List paramList = new List();
            if (parameterDefs != null)
            { 
                foreach (AST.PropDefinition paramDef in parameterDefs)
                { 
                    string name = paramDef.Name.Name; 

                    // 
                    // Validate param name
                    //
                    if (paramList.Exists((DbVariableReferenceExpression arg) =>
                                          sr.StringComparer.Compare(arg.VariableName, name) == 0)) 
                    {
                        throw EntityUtil.EntitySqlError( 
                            paramDef.ErrCtx, 
                            Strings.MultipleDefinitionsOfParameter(name));
                    } 

                    //
                    // Convert parameter type
                    // 
                    TypeUsage typeUsage = ConvertTypeDefinition(paramDef.Type, sr);
                    Debug.Assert(typeUsage != null, "typeUsage must not be null"); 
 
                    //
                    // Create function parameter ref expression 
                    //
                    DbVariableReferenceExpression paramRefExpr = new DbVariableReferenceExpression(typeUsage, name);
                    paramList.Add(paramRefExpr);
                } 
            }
            return paramList; 
        } 

        private sealed class InlineFunctionInfoImpl : InlineFunctionInfo 
        {
            private DbLambda _convertedDefinition = null;
            private bool _convertingDefinition = false;
 
            internal InlineFunctionInfoImpl(AST.FunctionDefinition functionDef, List parameters)
                : base(functionDef, parameters) 
            { 
            }
 
            internal override DbLambda GetLambda(SemanticResolver sr)
            {
                if (_convertedDefinition == null)
                { 
                    //
                    // Check for recursive definitions. 
                    // 
                    if (_convertingDefinition)
                    { 
                        throw EntityUtil.EntitySqlError(FunctionDefAst.ErrCtx, Strings.Cqt_UDF_FunctionDefinitionWithCircularReference(FunctionDefAst.Name));
                    }

                    // 
                    // Create a copy of semantic resolver without query scope entries to guarantee proper variable bindings inside the function body.
                    // The srSandbox shares InlineFunctionInfo objects with the original semantic resolver (sr), hence all the indirect conversions of 
                    // inline functions (in addition to this direct one) will also be visible in the original semantic resolver. 
                    //
                    SemanticResolver srSandbox = sr.CloneForInlineFunctionConversion(); 

                    _convertingDefinition = true;
                    _convertedDefinition = SemanticAnalyzer.ConvertInlineFunctionDefinition(this, srSandbox);
                    _convertingDefinition = false; 
                }
                return _convertedDefinition; 
            } 
        }
 
        private static DbLambda ConvertInlineFunctionDefinition(InlineFunctionInfo functionInfo, SemanticResolver sr)
        {
            //
            // Push function definition scope. 
            //
            sr.EnterScope(); 
 
            //
            // Add function parameters to the scope. 
            //
            functionInfo.Parameters.ForEach(p => sr.CurrentScope.Add(p.VariableName, new FreeVariableScopeEntry(p)));

            // 
            // Convert function body expression
            // 
            DbExpression body = ConvertValueExpression(functionInfo.FunctionDefAst.Body, sr); 

            // 
            // Pop function definition scope
            //
            sr.LeaveScope();
 
            //
            // Create and return lambda representing the function body. 
            // 
            return DbExpressionBuilder.Lambda(body, functionInfo.Parameters);
        } 

        /// 
        /// Converts general expressions (AST.Node)
        ///  
        private static ExpressionResolution Convert(AST.Node astExpr, SemanticResolver sr)
        { 
            AstExprConverter converter = _astExprConverters[astExpr.GetType()]; 
            if (converter == null)
            { 
                throw EntityUtil.EntitySqlError(Strings.UnknownAstExpressionType);
            }
            return converter(astExpr, sr);
        } 

        ///  
        /// Converts general expressions (AST.Node) to a . 
        /// Returns .
        /// Throws if conversion resulted an a non  resolution. 
        /// 
        private static DbExpression ConvertValueExpression(AST.Node astExpr, SemanticResolver sr)
        {
            ExpressionResolution resolution = Convert(astExpr, sr); 
            if (resolution.ExpressionClass == ExpressionResolutionClass.Value)
            { 
                return ((ValueExpression)resolution).Value; 
            }
            else 
            {
                string errorMessage = Strings.InvalidExpressionResolutionClass(resolution.ExpressionClassName, ValueExpression.ValueClassName);

                AST.Identifier identifier = astExpr as AST.Identifier; 
                if (identifier != null)
                { 
                    errorMessage = Strings.CouldNotResolveIdentifier(identifier.Name); 
                }
 
                AST.DotExpr dotExpr = astExpr as AST.DotExpr;
                string[] names;
                if (dotExpr != null && dotExpr.IsMultipartIdentifier(out names))
                { 
                    errorMessage = Strings.CouldNotResolveIdentifier(TypeResolver.GetFullName(names));
                } 
 
                throw EntityUtil.EntitySqlError(astExpr.ErrCtx, errorMessage);
            } 
        }

        /// 
        /// Converts literal expression (AST.Literal) 
        /// 
        private static ExpressionResolution ConvertLiteral(AST.Node expr, SemanticResolver sr) 
        { 
            AST.Literal literal = (AST.Literal)expr;
 
            if (literal.IsNullLiteral)
            {
                //
                // If it is literal null, return untyped null, 
                // untyped nulls will later have their type inferred depending on the
                // especific expression in which it participates. 
                // 
                return new ValueExpression(new UntypedNullExpression());
            } 
            else
            {
                return new ValueExpression(DbExpressionBuilder.Constant(GetLiteralTypeUsage(literal), literal.Value));
            } 
        }
 
        private static TypeUsage GetLiteralTypeUsage(AST.Literal literal) 
        {
            PrimitiveType primitiveType = null; 

            if (!ClrProviderManifest.Instance.TryGetPrimitiveType(literal.Type, out primitiveType))
            {
                throw EntityUtil.EntitySqlError(literal.ErrCtx, Strings.LiteralTypeNotFoundInMetadata(literal.OriginalValue)); 
            }
            TypeUsage literalTypeUsage = TypeHelpers.GetLiteralTypeUsage(primitiveType.PrimitiveTypeKind, literal.IsUnicodeString); 
 
            return literalTypeUsage;
        } 

        /// 
        /// Converts identifier expression (Identifier)
        ///  
        private static ExpressionResolution ConvertIdentifier(AST.Node expr, SemanticResolver sr)
        { 
            return ConvertIdentifier(((AST.Identifier)expr), false /* leftHandSideOfMemberAccess */, sr); 
        }
 
        private static ExpressionResolution ConvertIdentifier(AST.Identifier identifier, bool leftHandSideOfMemberAccess, SemanticResolver sr)
        {
            return sr.ResolveSimpleName(((AST.Identifier)identifier).Name, leftHandSideOfMemberAccess, identifier.ErrCtx);
        } 

        ///  
        /// Converts member access expression (AST.DotExpr) 
        /// 
        private static ExpressionResolution ConvertDotExpr(AST.Node expr, SemanticResolver sr) 
        {
            AST.DotExpr dotExpr = (AST.DotExpr)expr;

            ValueExpression groupKeyResolution; 
            if (sr.TryResolveDotExprAsGroupKeyAlternativeName(dotExpr, out groupKeyResolution))
            { 
                return groupKeyResolution; 
            }
 
            //
            // If dotExpr.Left is an identifier, then communicate to the resolution mechanism
            // that the identifier might be an unqualified name in the context of a qualified name.
            // Otherwise convert the expr normally. 
            //
            ExpressionResolution leftResolution; 
            AST.Identifier leftIdentifier = dotExpr.Left as AST.Identifier; 
            if (leftIdentifier != null)
            { 
                leftResolution = ConvertIdentifier(leftIdentifier, true /* leftHandSideOfMemberAccess */, sr);
            }
            else
            { 
                leftResolution = Convert(dotExpr.Left, sr);
            } 
 
            switch (leftResolution.ExpressionClass)
            { 
                case ExpressionResolutionClass.Value:
                    return sr.ResolvePropertyAccess(((ValueExpression)leftResolution).Value, dotExpr.Identifier.Name, dotExpr.Identifier.ErrCtx);

                case ExpressionResolutionClass.EntityContainer: 
                    return sr.ResolveEntitySetAccess(((EntityContainerExpression)leftResolution).EntityContainer, dotExpr.Identifier.Name, dotExpr.Identifier.ErrCtx);
 
                case ExpressionResolutionClass.MetadataMember: 
                    return sr.ResolveMetadataMemberAccess((MetadataMember)leftResolution, dotExpr.Identifier.Name, dotExpr.Identifier.ErrCtx);
 
                default:
                    throw EntityUtil.EntitySqlError(dotExpr.Left.ErrCtx, Strings.UnknownExpressionResolutionClass(leftResolution.ExpressionClass));
            }
        } 

        ///  
        /// Converts paren expression (AST.ParenExpr) 
        /// 
        private static ExpressionResolution ConvertParenExpr(AST.Node astExpr, SemanticResolver sr) 
        {
            AST.Node innerExpr = ((AST.ParenExpr)astExpr).Expr;

            // 
            // Convert the inner expression.
            // Note that we allow it to be an untyped null: the consumer of this expression will handle it. 
            // The reason to allow untyped nulls is that "(null)" is a common construct for tool-generated eSQL. 
            //
            DbExpression converted = ConvertValueExpression(innerExpr, sr); 
            Debug.Assert(converted != null, "converted != null");

            return new ValueExpression(converted);
        } 

        ///  
        /// Converts GROUPPARTITION expression (AST.GroupPartitionExpr). 
        /// 
        private static ExpressionResolution ConvertGroupPartitionExpr(AST.Node astExpr, SemanticResolver sr) 
        {
            AST.GroupPartitionExpr groupAggregateExpr = (AST.GroupPartitionExpr)astExpr;

            DbExpression converted = null; 

            // 
            // If ast node was annotated in a previous pass, means it contains a ready-to-use expression. 
            //
            if (!TryConvertAsResolvedGroupAggregate(groupAggregateExpr, sr, out converted)) 
            {
                //
                // GROUPPARTITION is allowed only in the context of a group operation provided by a query expression (SELECT ...).
                // 
                if (!sr.IsInAnyGroupScope())
                { 
                    throw EntityUtil.EntitySqlError(astExpr.ErrCtx, Strings.GroupPartitionOutOfContext); 
                }
 
                //
                // Process aggregate argument.
                //
                DbExpression arg; 
                GroupPartitionInfo aggregateInfo;
                using (sr.EnterGroupPartition(groupAggregateExpr, groupAggregateExpr.ErrCtx, out aggregateInfo)) 
                { 
                    //
                    // Convert aggregate argument. 
                    //
                    arg = ConvertValueExpression(groupAggregateExpr.ArgExpr, sr);
                    Debug.Assert(arg != null, "GROUPPARTITION argument conversion returned null.");
                } 

                // 
                // Ensure converted GROUPPARTITION argument expression is not untyped null. 
                //
                if (TypeSemantics.IsNullType(arg.ResultType)) 
                {
                    throw EntityUtil.EntitySqlError(groupAggregateExpr.ArgExpr.ErrCtx, Strings.ResultingExpressionTypeCannotBeNull);
                }
 
                //
                // Project the argument off the DbGroupAggregate binding. 
                // 
                DbExpression definition = aggregateInfo.EvaluatingScopeRegion.GroupAggregateBinding.Project(arg);
 
                if (groupAggregateExpr.DistinctKind == AST.DistinctKind.Distinct)
                {
                    ValidateDistinctProjection(definition.ResultType, groupAggregateExpr.ArgExpr.ErrCtx, null);
                    definition = definition.Distinct(); 
                }
 
                // 
                // Add aggregate to aggreate list.
                // 
                aggregateInfo.AttachToAstNode(sr.GenerateInternalName("groupPartition"), definition);
                aggregateInfo.EvaluatingScopeRegion.GroupAggregateInfos.Add(aggregateInfo);

                // 
                // Return stub expression with same type as the group aggregate.
                // 
                converted = aggregateInfo.AggregateStubExpression; 
            }
 
            Debug.Assert(null != converted, "null != converted");

            return new ValueExpression(converted);
        } 

        #region ConvertMethodExpr implementation 
        ///  
        /// Converts invocation expression (AST.MethodExpr)
        ///  
        private static ExpressionResolution ConvertMethodExpr(AST.Node expr, SemanticResolver sr)
        {
            return ConvertMethodExpr((AST.MethodExpr)expr, true /* includeInlineFunctions */, sr);
        } 

        private static ExpressionResolution ConvertMethodExpr(AST.MethodExpr methodExpr, bool includeInlineFunctions, SemanticResolver sr) 
        { 
            //
            // Resolve methodExpr.Expr 
            //
            ExpressionResolution leftResolution;
            using (sr.TypeResolver.EnterFunctionNameResolution(includeInlineFunctions))
            { 
                AST.Identifier simpleFunctionName = methodExpr.Expr as AST.Identifier;
                if (simpleFunctionName != null) 
                { 
                    //
                    // If methodExpr.Expr is an identifier, it represents a simple function name. Resolve it as an unqualified name by calling the type resolver directly. 
                    // Note that calling type resolver directly will avoid resolution of the identifier as a value / entity container / entity set expression (these resolutions are
                    // performed only by semantic resolver).
                    //
                    leftResolution = sr.TypeResolver.ResolveUnqualifiedName(simpleFunctionName.Name, false /* partOfQualifiedName */, simpleFunctionName.ErrCtx); 
                }
                else 
                { 
                    //
                    // Convert methodExpr.Expr optionally entering special resolution modes. See ConvertMethodExpr_TryEnter methods for more info. 
                    //
                    AST.DotExpr dotExpr = methodExpr.Expr as AST.DotExpr;
                    using (ConvertMethodExpr_TryEnterIgnoreEntityContainerNameResolution(dotExpr, sr))
                    { 
                        using (ConvertMethodExpr_TryEnterBackwardCompatibilityResolution(dotExpr, sr))
                        { 
                            leftResolution = Convert(methodExpr.Expr, sr); 
                        }
                    } 
                }
            }

            if (leftResolution.ExpressionClass == ExpressionResolutionClass.MetadataMember) 
            {
                MetadataMember metadataMember = (MetadataMember)leftResolution; 
 
                //
                // Try converting as inline function call. If it fails, continue. 
                //
                ValueExpression inlineFunctionCall;
                if (metadataMember.MetadataMemberClass == MetadataMemberClass.InlineFunctionGroup)
                { 
                    Debug.Assert(includeInlineFunctions, "includeInlineFunctions must be true, otherwise recursion does not stop");
 
                    methodExpr.ErrCtx.ErrorContextInfo = Strings.CtxFunction(metadataMember.Name); 
                    methodExpr.ErrCtx.UseContextInfoAsResourceIdentifier = false;
                    if (TryConvertInlineFunctionCall((InlineFunctionGroup)metadataMember, methodExpr, sr, out inlineFunctionCall)) 
                    {
                        return inlineFunctionCall;
                    }
                    else 
                    {
                        return ConvertMethodExpr(methodExpr, false /* includeInlineFunctions */, sr); 
                    } 
                }
 
                switch (metadataMember.MetadataMemberClass)
                {
                    case MetadataMemberClass.Type:
                        methodExpr.ErrCtx.ErrorContextInfo = Strings.CtxTypeCtor(metadataMember.Name); 
                        methodExpr.ErrCtx.UseContextInfoAsResourceIdentifier = false;
                        return ConvertTypeConstructorCall((MetadataType)metadataMember, methodExpr, sr); 
 
                    case MetadataMemberClass.FunctionGroup:
                        methodExpr.ErrCtx.ErrorContextInfo = Strings.CtxFunction(metadataMember.Name); 
                        methodExpr.ErrCtx.UseContextInfoAsResourceIdentifier = false;
                        return ConvertModelFunctionCall((MetadataFunctionGroup)metadataMember, methodExpr, sr);

                    default: 
                        throw EntityUtil.EntitySqlError(methodExpr.Expr.ErrCtx, Strings.CannotResolveNameToTypeOrFunction(metadataMember.Name));
                } 
            } 
            else
            { 
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.MethodInvocationNotSupported);
            }
        }
 
        /// 
        /// If methodExpr.Expr is in the form of "Name1.Name2(...)" then ignore entity containers during resolution of the left expression 
        /// in the context of the invocation: "EntityContainer.EntitySet(...)" is not a valid expression and it should not shadow 
        /// a potentially valid interpretation as "Namespace.EntityType/Function(...)".
        ///  
        private static IDisposable ConvertMethodExpr_TryEnterIgnoreEntityContainerNameResolution(AST.DotExpr leftExpr, SemanticResolver sr)
        {
            return leftExpr != null && leftExpr.Left is AST.Identifier ? sr.EnterIgnoreEntityContainerNameResolution() : null;
        } 

        ///  
        /// If methodExpr.Expr is in the form of "Name1.Name2(...)" 
        /// and we are in the view generation mode
        /// and schema version is less than V2 
        /// then ignore types in the resolution of Name1.
        /// This is needed in order to support the following V1 case:
        ///     C-space type: AdventureWorks.Store
        ///     S-space type: [AdventureWorks.Store].Customer 
        ///     query: select [AdventureWorks.Store].Customer(1, 2, 3) from ...
        ///  
        private static IDisposable ConvertMethodExpr_TryEnterBackwardCompatibilityResolution(AST.DotExpr leftExpr, SemanticResolver sr) 
        {
            if (leftExpr != null && leftExpr.Left is AST.Identifier && 
                (sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode ||
                sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.UserViewGenerationMode) &&
                sr.TypeResolver.Perspective.MetadataWorkspace.SchemaVersion < XmlConstants.EdmVersionForV2)
            { 
                return sr.TypeResolver.EnterBackwardCompatibilityResolution();
            } 
            else 
            {
                return null; 
            }
        }

        ///  
        /// Attempts to create a  representing the inline function call.
        /// Returns false if .DistinctKind != .None. 
        /// Returns false if no one of the overloads matched the given arguments. 
        /// Throws if given arguments cause overload resolution ambiguity.
        ///  
        private static bool TryConvertInlineFunctionCall(
            InlineFunctionGroup inlineFunctionGroup,
            AST.MethodExpr methodExpr,
            SemanticResolver sr, 
            out ValueExpression inlineFunctionCall)
        { 
            inlineFunctionCall = null; 

            // 
            // An inline function can't be a group aggregate, so if DistinctKind is specified then it is not an inline function call.
            //
            if (methodExpr.DistinctKind != AST.DistinctKind.None)
            { 
                return false;
            } 
 
            //
            // Convert function arguments. 
            //
            List args = ConvertFunctionArguments(methodExpr.Args, sr);

            // 
            // Collect argument types from argument expression list.
            // 
            List argTypes = new List(args.Count); 
            for (int i = 0; i < args.Count; i++)
            { 
                argTypes.Add(args[i].ResultType);
            }

            // 
            // Find function overload match for the given argument types.
            // 
            bool isAmbiguous = false; 
            InlineFunctionInfo overload = FunctionOverloadResolver.ResolveFunctionOverloads(
                inlineFunctionGroup.FunctionMetadata, 
                argTypes,
                (lambdaOverload) => lambdaOverload.Parameters,
                (varRef) => varRef.ResultType,
                (varRef) => ParameterMode.In, 
                false /* isGroupAggregateFunction */,
                out isAmbiguous); 
 
            //
            // If there is more than one overload that matches the given arguments, throw. 
            //
            if (isAmbiguous)
            {
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.AmbiguousFunctionArguments); 
            }
 
            // 
            // If null, means no overload matched.
            // 
            if (overload == null)
            {
                return false;
            } 

            // 
            // Convert untyped NULLs in arguments to typed nulls derived from formals. 
            //
            ConvertUntypedNullsInArguments(args, overload.Parameters, (formal) => formal.ResultType); 

            inlineFunctionCall = new ValueExpression(DbExpressionBuilder.Invoke(overload.GetLambda(sr), args));
            return true;
        } 

        private static ValueExpression ConvertTypeConstructorCall(MetadataType metadataType, AST.MethodExpr methodExpr, SemanticResolver sr) 
        { 
            //
            // Ensure type has a contructor. 
            //
            if (!TypeSemantics.IsComplexType(metadataType.TypeUsage) &&
                !TypeSemantics.IsEntityType(metadataType.TypeUsage) &&
                !TypeSemantics.IsRelationshipType(metadataType.TypeUsage)) 
            {
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.InvalidCtorUseOnType(TypeHelpers.GetFullName(metadataType.TypeUsage))); 
            } 

            // 
            // Abstract types cannot be instantiated.
            //
            if (metadataType.TypeUsage.EdmType.Abstract)
            { 
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.CannotInstantiateAbstractType(TypeHelpers.GetFullName(metadataType.TypeUsage)));
            } 
 
            //
            // DistinctKind must not be specified on a type constructor. 
            //
            if (methodExpr.DistinctKind != AST.DistinctKind.None)
            {
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.InvalidDistinctArgumentInCtor); 
            }
 
            // 
            // Convert relationships if present.
            // 
            List relshipExprList = null;
            if (methodExpr.HasRelationships)
            {
                if (!(sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode || 
                      sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.UserViewGenerationMode))
                { 
                    throw EntityUtil.EntitySqlError(methodExpr.Relationships.ErrCtx, Strings.InvalidModeForWithRelationshipClause); 
                }
 
                HashSet targetEnds = new HashSet();
                relshipExprList = new List(methodExpr.Relationships.Count);
                for (int i = 0; i < methodExpr.Relationships.Count; i++)
                { 
                    AST.RelshipNavigationExpr relshipExpr = methodExpr.Relationships[i];
 
                    DbRelatedEntityRef relshipTarget = ConvertRelatedEntityRef(relshipExpr, sr); 

                    string targetEndId = String.Join(":", new String[] { relshipTarget.TargetEnd.DeclaringType.Identity, relshipTarget.TargetEnd.Identity }); 
                    if (targetEnds.Contains(targetEndId))
                    {
                        throw EntityUtil.EntitySqlError(relshipExpr.ErrCtx,
                            Strings.RelationshipTargetMustBeUnique(relshipTarget.TargetEntityReference.ResultType.EdmType.Identity)); 
                    }
 
                    targetEnds.Add(targetEndId); 

                    relshipExprList.Add(relshipTarget); 
                }
            }

            return new ValueExpression(CreateConstructorCallExpression(methodExpr, 
                                                                       metadataType.TypeUsage,
                                                                       ConvertFunctionArguments(methodExpr.Args, sr), 
                                                                       relshipExprList, 
                                                                       sr));
        } 

        private static ValueExpression ConvertModelFunctionCall(MetadataFunctionGroup metadataFunctionGroup, AST.MethodExpr methodExpr, SemanticResolver sr)
        {
            // 
            // Decide if it is an ordinary function or group aggregate
            // 
            if (TypeSemantics.IsAggregateFunction(metadataFunctionGroup.FunctionMetadata[0]) && sr.IsInAnyGroupScope()) 
            {
                // 
                // If it is an aggreagate function inside a group scope, dispatch to the expensive ConvertAggregateFunctionInGroupScope()...
                //
                return new ValueExpression(ConvertAggregateFunctionInGroupScope(methodExpr, metadataFunctionGroup, sr));
            } 
            else
            { 
                // 
                // Otherwise, it is just an ordinary function call (including aggregate functions outside of a group scope)
                // 
                return new ValueExpression(CreateModelFunctionCallExpression(methodExpr, metadataFunctionGroup, sr));
            }
        }
 
        #region ConvertAggregateFunctionInGroupScope implementation
        ///  
        /// Converts group aggregates. 
        /// 
        ///  
        /// This method converts group aggregates in two phases:
        /// Phase 1 - it will resolve the actual inner (argument) expression and then anotate the ast node and add the resolved aggregate
        /// to the scope
        /// Phase 2 - if ast node was annotated, just extract the precomputed expression from the scope. 
        /// 
        private static DbExpression ConvertAggregateFunctionInGroupScope(AST.MethodExpr methodExpr, MetadataFunctionGroup metadataFunctionGroup, SemanticResolver sr) 
        { 
            DbExpression converted = null;
 
            //
            // First, check if methodExpr is already resolved as an aggregate...
            //
            if (TryConvertAsResolvedGroupAggregate(methodExpr, sr, out converted)) 
            {
                return converted; 
            } 

            // 
            // ... then, try to convert as a collection function.
            //
            // Note that if methodExpr represents a group aggregate,
            // then the argument conversion performed inside of TryConvertAsCollectionFunction(...) is thrown away. 
            // Throwing the argument conversion however is not possible in a clean way as the argument conversion has few side-effects:
            // 1. For each group aggregate within the argument a new GroupAggregateInfo object is created and: 
            //    a. Some of the aggregates are assigned to outer scope regions for evaluation, which means their aggregate info objects are 
            //         - enlisted in the outer scope regions,
            //         - remain attached to the corresponding AST nodes, see GroupAggregateInfo.AttachToAstNode(...) for more info. 
            //       These aggregate info objects will be reused when the aggregates are revisited, see TryConvertAsResolvedGroupAggregate(...) method for more info.
            //    b. The aggregate info objects of closest aggregates are wired to sr.CurrentGroupAggregateInfo object as contained/containing.
            // 2. sr.CurrentGroupAggregateInfo.InnermostReferencedScopeRegion value is adjusted with all the scope entry references outside of nested aggregates.
            // Hence when the conversion as a collection function fails, these side-effects must be mitigated: 
            // (1.a) does not cause any issues.
            // (1.b) requires rewiring which is handled by the GroupAggregateInfo.SetContainingAggregate(...) mechanism invoked by 
            //       TryConvertAsResolvedGroupAggregate(...) method. 
            // (2) requires saving and restoring the InnermostReferencedScopeRegion value, which is handled in the code below.
            // 
            // Note: we also do a throw-away conversions in other places, such as inline function attempt and processing of projection items in order by clause,
            // but this method is the only place where conversion attempts differ in the way how converted argument expression is processed.
            // This method is the only place that affects sr.CurrentGroupAggregateInfo with regard to the converted argument expression.
            // Hence the side-effect mitigation is needed only here. 
            //
            ScopeRegion savedInnermostReferencedScopeRegion = sr.CurrentGroupAggregateInfo != null ? sr.CurrentGroupAggregateInfo.InnermostReferencedScopeRegion : null; 
            List argTypes; 
            if (TryConvertAsCollectionFunction(methodExpr, metadataFunctionGroup, sr, out argTypes, out converted))
            { 
                return converted;
            }
            else if (sr.CurrentGroupAggregateInfo != null)
            { 
                sr.CurrentGroupAggregateInfo.InnermostReferencedScopeRegion = savedInnermostReferencedScopeRegion;
            } 
            Debug.Assert(argTypes != null, "argTypes != null"); 

            // 
            // Finally, try to convert as a function group aggregate.
            //
            if (TryConvertAsFunctionAggregate(methodExpr, metadataFunctionGroup, argTypes, sr, out converted))
            { 
                return converted;
            } 
 
            //
            // If we reach this point, means the resolution failed. 
            //
            throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.FailedToResolveAggregateFunction(metadataFunctionGroup.Name));
        }
 
        /// 
        /// Try to convert as pre resolved group aggregate. 
        ///  
        private static bool TryConvertAsResolvedGroupAggregate(AST.GroupAggregateExpr groupAggregateExpr, SemanticResolver sr, out DbExpression converted)
        { 
            converted = null;

            //
            // If ast node was annotated in a previous pass, means it contains a ready-to-use expression, 
            // otherwise exit.
            // 
            if (groupAggregateExpr.AggregateInfo == null) 
            {
                return false; 
            }

            //
            // Wire up groupAggregateExpr.AggregateInfo to the sr.CurrentGroupAggregateInfo. 
            // This is needed in the following case:  ... select max(x + max(b)) ...
            // The outer max(...) is first processed as collection function, so when the nested max(b) is processed as an aggregate, it does not 
            // see the outer function as a containing aggregate, so it does not wire to it. 
            // Later, when the outer max(...) is processed as an aggregate, processing of the inner max(...) gets into TryConvertAsResolvedGroupAggregate(...)
            // and at this point we finally wire up the two aggregates. 
            //
            groupAggregateExpr.AggregateInfo.SetContainingAggregate(sr.CurrentGroupAggregateInfo);

            if (!sr.TryResolveInternalAggregateName(groupAggregateExpr.AggregateInfo.AggregateName, groupAggregateExpr.AggregateInfo.ErrCtx, out converted)) 
            {
                Debug.Assert(groupAggregateExpr.AggregateInfo.AggregateStubExpression != null, "Resolved aggregate stub expression must not be null."); 
                converted = groupAggregateExpr.AggregateInfo.AggregateStubExpression; 
            }
 
            Debug.Assert(converted != null, "converted != null");

            return true;
        } 

        ///  
        /// Try convert method expr in a group scope as a collection aggregate 
        /// 
        /// argTypes are returned regardless of the function result 
        private static bool TryConvertAsCollectionFunction(AST.MethodExpr methodExpr,
                                                           MetadataFunctionGroup metadataFunctionGroup,
                                                           SemanticResolver sr,
                                                           out List argTypes, 
                                                           out DbExpression converted)
        { 
            converted = null; 

            // 
            // Convert aggregate arguments.
            //
            List args = ConvertFunctionArguments(methodExpr.Args, sr);
 
            //
            // Collect argument types. 
            // 
            argTypes = new List(args.Count);
            for (int i = 0; i < args.Count; i++) 
            {
                argTypes.Add(args[i].ResultType);
            }
 
            //
            // Try to see if there is a overload match. 
            // 
            bool isAmbiguous = false;
            EdmFunction functionType = FunctionOverloadResolver.ResolveFunctionOverloads( 
                metadataFunctionGroup.FunctionMetadata,
                argTypes,
                false /* isGroupAggregateFunction */,
                out isAmbiguous); 

            // 
            // If there is more then one overload that matches given arguments, throw. 
            //
            if (isAmbiguous) 
            {
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.AmbiguousFunctionArguments);
            }
 
            //
            // If not null, means a match was found as a collection aggregate (ordinary function). 
            // 
            if (null != functionType)
            { 
                converted = functionType.Invoke(args);
            }

            return (null != functionType); 
        }
 
        private static bool TryConvertAsFunctionAggregate(AST.MethodExpr methodExpr, 
                                                          MetadataFunctionGroup metadataFunctionGroup,
                                                          List argTypes, 
                                                          SemanticResolver sr,
                                                          out DbExpression converted)
        {
            Debug.Assert(argTypes != null, "argTypes != null"); 

            converted = null; 
 
            //
            // Try to find an overload match as group aggregate 
            //
            bool isAmbiguous = false;
            EdmFunction functionType = FunctionOverloadResolver.ResolveFunctionOverloads(
                metadataFunctionGroup.FunctionMetadata, 
                argTypes,
                true /* isGroupAggregateFunction */, 
                out isAmbiguous); 

            // 
            // If there is more then one overload that matches given arguments, throw.
            //
            if (isAmbiguous)
            { 
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.AmbiguousFunctionArguments);
            } 
 
            //
            // If it still null, then there is no overload as a group aggregate function. 
            //
            if (null == functionType)
            {
                CqlErrorHelper.ReportFunctionOverloadError(methodExpr, metadataFunctionGroup.FunctionMetadata[0], argTypes); 
            }
            // 
            // Process aggregate argument. 
            //
            List args; 
            FunctionAggregateInfo aggregateInfo;
            using (sr.EnterFunctionAggregate(methodExpr, methodExpr.ErrCtx, out aggregateInfo))
            {
                args = ConvertFunctionArguments(methodExpr.Args, sr); 
                // Sanity check - argument types must agree.
                Debug.Assert( 
                    argTypes.Count == args.Count && 
                    argTypes.Zip(args.Select(arg => arg.ResultType)).All(types => TypeSemantics.IsStructurallyEqual(types.Key, types.Value)),
                    "argument types resolved for the collection aggregate calls must match"); 
            }

            //
            // Aggregate functions can have only one argument and of collection type 
            //
            Debug.Assert((1 == functionType.Parameters.Count), "(1 == functionType.Parameters.Count)"); // we only support monadic aggregate functions 
            Debug.Assert(TypeSemantics.IsCollectionType(functionType.Parameters[0].TypeUsage), "functionType.Parameters[0].Type is CollectionType"); 

            // 
            // Convert untyped NULLs in arguments to typed nulls derived from function parameters.
            //
            ConvertUntypedNullsInArguments(args, functionType.Parameters, (functionParameter) => TypeHelpers.GetElementTypeUsage(functionParameter.TypeUsage));
 
            //
            // Create function aggregate expression. 
            // 
            DbFunctionAggregate functionAggregate;
            if (methodExpr.DistinctKind == AST.DistinctKind.Distinct) 
            {
                functionAggregate = DbExpressionBuilder.AggregateDistinct(functionType, args[0]);
            }
            else 
            {
                functionAggregate = DbExpressionBuilder.Aggregate(functionType, args[0]); 
            } 

            // 
            // Add aggregate to aggreate list.
            //
            aggregateInfo.AttachToAstNode(sr.GenerateInternalName("groupAgg" + functionType.Name), functionAggregate);
            aggregateInfo.EvaluatingScopeRegion.GroupAggregateInfos.Add(aggregateInfo); 

            // 
            // Return stub expression with same type as the aggregate function. 
            //
            converted = aggregateInfo.AggregateStubExpression; 

            Debug.Assert(converted != null, "converted != null");

            return true; 
        }
        #endregion ConvertAggregateFunctionInGroupScope implementation 
 
        /// 
        /// Creates  representing a new instance of the given type. 
        /// Validates and infers argument types.
        /// 
        private static DbExpression CreateConstructorCallExpression(AST.MethodExpr methodExpr,
                                                                    TypeUsage type, 
                                                                    List args,
                                                                    List relshipExprList, 
                                                                    SemanticResolver sr) 
        {
            Debug.Assert(TypeSemantics.IsComplexType(type) || TypeSemantics.IsEntityType(type) || TypeSemantics.IsRelationshipType(type), "type must have a constructor"); 

            DbExpression newInstance = null;
            int idx = 0;
            int argCount = args.Count; 

            // 
            // Find overloads by searching members in order of its definition. 
            // Each member will be considered as a formal argument type in the order of its definition.
            // 
            StructuralType stype = (StructuralType)type.EdmType;
            foreach (EdmMember member in TypeHelpers.GetAllStructuralMembers(stype))
            {
                TypeUsage memberModelTypeUsage = Helper.GetModelTypeUsage(member); 

                Debug.Assert(memberModelTypeUsage.EdmType.DataSpace == DataSpace.CSpace, "member space must be CSpace"); 
 
                //
                // Ensure given arguments are not less than 'formal' constructor arguments. 
                //
                if (argCount <= idx)
                {
                    throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.NumberOfTypeCtorIsLessThenFormalSpec(member.Name)); 
                }
 
                // 
                // If the given argument is an untyped null, infer type from the ctor formal argument type.
                // 
                if (TypeSemantics.IsNullType(args[idx].ResultType))
                {
                    EdmProperty edmProperty = member as EdmProperty;
                    if ((edmProperty != null) && 
                        !(edmProperty.Nullable))
                    { 
                        throw EntityUtil.EntitySqlError(methodExpr.Args[idx].ErrCtx, 
                            Strings.InvalidNullLiteralForNonNullableMember(member.Name, TypeHelpers.GetFullName(stype)));
                    } 
                    args[idx] = DbExpressionBuilder.Null(memberModelTypeUsage);
                }

                // 
                // Ensure the given argument type is promotable to the formal ctor argument type.
                // 
                bool isPromotable = TypeSemantics.IsPromotableTo(args[idx].ResultType, memberModelTypeUsage); 
                if (ParserOptions.CompilationMode.RestrictedViewGenerationMode == sr.ParserOptions.ParserCompilationMode ||
                    ParserOptions.CompilationMode.UserViewGenerationMode == sr.ParserOptions.ParserCompilationMode) 
                {
                    if (!isPromotable && !TypeSemantics.IsPromotableTo(memberModelTypeUsage, args[idx].ResultType))
                    {
                        throw EntityUtil.EntitySqlError(methodExpr.Args[idx].ErrCtx, 
                            Strings.InvalidCtorArgumentType(
                                                       args[idx].ResultType.Identity, 
                                                       member.Name, 
                                                       memberModelTypeUsage.Identity));
                    } 

                    if (Helper.IsPrimitiveType(memberModelTypeUsage.EdmType) &&
                        !TypeSemantics.IsSubTypeOf(args[idx].ResultType, memberModelTypeUsage))
                    { 
                        args[idx] = args[idx].CastTo(memberModelTypeUsage);
                    } 
                } 
                else
                { 
                    if (!isPromotable)
                    {
                        throw EntityUtil.EntitySqlError(methodExpr.Args[idx].ErrCtx,
                            Strings.InvalidCtorArgumentType( 
                                                       args[idx].ResultType.Identity,
                                                       member.Name, 
                                                       memberModelTypeUsage.Identity)); 
                    }
                } 

                idx++;
            }
 
            //
            // Ensure all given arguments and all ctor formals were considered and properly checked. 
            // 
            if (idx != argCount)
            { 
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.NumberOfTypeCtorIsMoreThenFormalSpec(TypeHelpers.GetFullName(type)));
            }

            // 
            // Finally, create expression
            // 
            if (relshipExprList != null && relshipExprList.Count > 0) 
            {
                EntityType entityType = (EntityType)type.EdmType; 
                newInstance = DbExpressionBuilder.CreateNewEntityWithRelationshipsExpression(entityType, args, relshipExprList);
            }
            else
            { 
                newInstance = DbExpressionBuilder.New(TypeHelpers.GetReadOnlyType(type), args);
            } 
            Debug.Assert(null != newInstance, "null != newInstance"); 

            return newInstance; 
        }

        /// 
        /// Creates  representing a model function call. 
        /// Validates overloads.
        ///  
        private static DbFunctionExpression CreateModelFunctionCallExpression(AST.MethodExpr methodExpr, 
                                                                              MetadataFunctionGroup metadataFunctionGroup,
                                                                              SemanticResolver sr) 
        {
            DbFunctionExpression functionExpression = null;
            bool isAmbiguous = false;
 
            //
            // DistinctKind must not be specified on a regular function call. 
            // 
            if (methodExpr.DistinctKind != AST.DistinctKind.None)
            { 
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.InvalidDistinctArgumentInNonAggFunction);
            }

            // 
            // Convert function arguments.
            // 
            List args = ConvertFunctionArguments(methodExpr.Args, sr); 

            // 
            // Collect argument types from argument expression list.
            //
            List argTypes = new List(args.Count);
            for (int i = 0; i < args.Count; i++) 
            {
                argTypes.Add(args[i].ResultType); 
            } 

            // 
            // Find function overload match for given argument types.
            //
            EdmFunction functionType = FunctionOverloadResolver.ResolveFunctionOverloads(
                metadataFunctionGroup.FunctionMetadata, 
                argTypes,
                false /* isGroupAggregateFunction */, 
                out isAmbiguous); 

            // 
            // If there is more than one overload that matches given arguments, throw.
            //
            if (isAmbiguous)
            { 
                throw EntityUtil.EntitySqlError(methodExpr.ErrCtx, Strings.AmbiguousFunctionArguments);
            } 
 
            //
            // If null, means no overload matched. 
            //
            if (null == functionType)
            {
                CqlErrorHelper.ReportFunctionOverloadError(methodExpr, metadataFunctionGroup.FunctionMetadata[0], argTypes); 
            }
 
            // 
            // Convert untyped NULLs in arguments to typed nulls derived from function parameters.
            // 
            ConvertUntypedNullsInArguments(args, functionType.Parameters, (parameter) => parameter.TypeUsage);

            //
            // Finally, create expression 
            //
            functionExpression = functionType.Invoke(args); 
 
            Debug.Assert(null != functionExpression, "null != functionExpression");
 
            return functionExpression;
        }

        ///  
        /// Converts function call arguments into a list of s.
        /// In case of no arguments returns an empty list. 
        ///  
        private static List ConvertFunctionArguments(AST.NodeList astExprList, SemanticResolver sr)
        { 
            List convertedArgs = new List();

            if (null != astExprList)
            { 
                for (int i = 0; i < astExprList.Count; i++)
                { 
                    convertedArgs.Add(ConvertValueExpression(astExprList[i], sr)); 
                }
            } 

            return convertedArgs;
        }
 
        private static void ConvertUntypedNullsInArguments(
            List args, 
            IList parametersMetadata, 
            Func getParameterTypeUsage)
        { 
            for (int i = 0; i < args.Count; i++)
            {
                if (TypeSemantics.IsNullType(args[i].ResultType))
                { 
                    args[i] = DbExpressionBuilder.Null(getParameterTypeUsage(parametersMetadata[i]));
                } 
            } 
        }
        #endregion ConvertMethodExpr implementation 

        /// 
        /// Converts command parameter reference expression (AST.QueryParameter)
        ///  
        private static ExpressionResolution ConvertParameter(AST.Node expr, SemanticResolver sr)
        { 
            AST.QueryParameter parameter = (AST.QueryParameter)expr; 

            DbParameterReferenceExpression paramRef; 
            if (null == sr.Parameters || !sr.Parameters.TryGetValue(parameter.Name, out paramRef))
            {
                throw EntityUtil.EntitySqlError(parameter.ErrCtx, Strings.ParameterWasNotDefined(parameter.Name));
            } 

            return new ValueExpression(paramRef); 
        } 

        ///  
        /// Validate a relationship-traversal - used for both Navigate expressions
        /// and for entity construction with related entity refs.
        ///
        /// For "related entity refs", "isTargetEnd" is true - for Navigate expressions, 
        /// this parameter is "false".
        /// 
        ///  
        /// the relationshipExpr AST
        ///  
        /// resolver context
        /// the source/target expression
        /// the relationship type
        /// from end of the relationship 
        /// to-end of the relationship
        private static void ValidateRelationshipTraversal(AST.RelshipNavigationExpr relshipExpr, 
                                                          bool isTargetEnd, 
                                                          SemanticResolver sr,
                                                          out DbExpression refExpr, 
                                                          out RelationshipType relationshipType,
                                                          out RelationshipEndMember refEnd,
                                                          out RelationshipEndMember otherEnd)
        { 
            relationshipType = null;
            refEnd = null; 
            otherEnd = null; 
            refExpr = null;
 
            //
            // Resolve relationship type name.
            //
            relationshipType = ConvertTypeName(relshipExpr.TypeName, sr).EdmType as RelationshipType; 
            Debug.Assert(relationshipType != null, "resolved relationshipType must not be null");
 
            // 
            // Convert relationship instance expression.
            // 
            refExpr = ConvertValueExpression(relshipExpr.Source, sr);

            //
            // If is entity, create entity ref out if it. 
            //
            if (!isTargetEnd && TypeSemantics.IsEntityType(refExpr.ResultType)) 
            { 
                refExpr = refExpr.GetEntityRef();
            } 

            //
            // Make sure it is a ref type.
            // 
            if (!TypeSemantics.IsReferenceType(refExpr.ResultType))
            { 
                throw EntityUtil.EntitySqlError(relshipExpr.Source.ErrCtx, Strings.InvalidRelationshipSourceType); 
            }
 
            //
            // Ensure entity participates in the given relationship type.
            //
            if (!TypeSemantics.IsTypeValidForRelationship(TypeHelpers.GetElementTypeUsage(refExpr.ResultType), relationshipType)) 
            {
                throw EntityUtil.EntitySqlError(relshipExpr.TypeName.ErrCtx, Strings.RelationshipTypeIsNotCompatibleWithEntity( 
                    TypeHelpers.GetFullName(TypeHelpers.GetElementTypeUsage(refExpr.ResultType)), 
                    TypeHelpers.GetFullName(relationshipType)));
            } 

            //
            // Ensure relationship ends are valid.
            // Metadata ensures uniqueness of end names. 
            //
            TypeUsage fromEndType = null; 
            int fromEndMatchCount = 0; 
            TypeUsage elementType = TypeHelpers.GetElementTypeUsage(refExpr.ResultType);
            for (int i = 0; i < relationshipType.Members.Count; i++) 
            {
                //
                // Check TO end.
                // 
                if (relshipExpr.ToEndIdentifier != null && relationshipType.Members[i].Name.Equals(relshipExpr.ToEndIdentifier.Name, StringComparison.OrdinalIgnoreCase))
                { 
                    otherEnd = (RelationshipEndMember)relationshipType.Members[i]; 
                    continue;
                } 

                //
                // Check FROM end.
                // 
                if (
                    (null != relshipExpr.FromEndIdentifier && relationshipType.Members[i].Name.Equals(relshipExpr.FromEndIdentifier.Name, StringComparison.OrdinalIgnoreCase)) || 
                    (null == relshipExpr.FromEndIdentifier && TypeSemantics.IsStructurallyEqualOrPromotableTo(elementType, TypeHelpers.GetElementTypeUsage(relationshipType.Members[i].TypeUsage))) 
                   )
                { 
                    fromEndMatchCount++;

                    if (fromEndMatchCount > 1)
                    { 
                        ErrorContext errCtx = (null == relshipExpr.FromEndIdentifier) ? relshipExpr.ErrCtx : relshipExpr.FromEndIdentifier.ErrCtx;
 
                        throw EntityUtil.EntitySqlError(errCtx, Strings.RelationshipFromEndIsAmbiguos); 
                    }
 
                    refEnd = (RelationshipEndMember)relationshipType.Members[i];
                    fromEndType = relationshipType.Members[i].TypeUsage;
                }
            } 

            // 
            // Ensure TO end contains given property. 
            //
            if (null == otherEnd) 
            {
                if (null != relshipExpr.ToEndIdentifier)
                {
                    throw EntityUtil.EntitySqlError(relshipExpr.ToEndIdentifier.ErrCtx, Strings.InvalidRelationshipMember(relshipExpr.ToEndIdentifier.Name, relationshipType.FullName)); 
                }
 
                if (2 != relationshipType.Members.Count) 
                {
                    throw EntityUtil.EntitySqlError(relshipExpr.ErrCtx, Strings.InvalidImplicitRelationshipToEnd(relationshipType.FullName)); 
                }

                Debug.Assert(null != refEnd, "null!=fromEnd");
 
                otherEnd = (RelationshipEndMember)(refEnd.Name.Equals(relationshipType.Members[0].Name, StringComparison.OrdinalIgnoreCase) ? relationshipType.Members[1] : relationshipType.Members[0]);
            } 
 
            //
            // Ensure FROM end contains given entity. 
            //
            if (null == refEnd || null == fromEndType)
            {
                ErrorContext errCtx = (null == relshipExpr.FromEndIdentifier) ? relshipExpr.ErrCtx : relshipExpr.FromEndIdentifier.ErrCtx; 

                if (null == relshipExpr.FromEndIdentifier) 
                { 
                    throw EntityUtil.EntitySqlError(errCtx, Strings.InvalidImplicitRelationshipFromEnd(relationshipType.FullName));
                } 
                else
                {
                    throw EntityUtil.EntitySqlError(errCtx, Strings.InvalidRelationshipMember(relshipExpr.FromEndIdentifier.Name, relationshipType.FullName));
                } 
            }
 
            // 
            // Check that source is promotable to FROM end type.
            // 
            if (!TypeSemantics.IsValidPolymorphicCast(TypeHelpers.GetElementTypeUsage(refExpr.ResultType),
                                                      TypeHelpers.GetElementTypeUsage(refEnd.TypeUsage)))
            {
                ErrorContext errCtx = (null == relshipExpr.FromEndIdentifier) ? relshipExpr.ErrCtx : relshipExpr.FromEndIdentifier.ErrCtx; 

                throw EntityUtil.EntitySqlError(errCtx, Strings.SourceTypeMustBePromotoableToFromEndRelationType(TypeHelpers.GetElementTypeUsage(refExpr.ResultType).EdmType.FullName, TypeHelpers.GetElementTypeUsage(fromEndType).EdmType.FullName)); 
            } 

            return; 
        }

        /// 
        /// Build out a RelatedEntityRef 
        /// 
        /// the ast expression 
        /// the Semantic Resolver context 
        /// a DbRelatedEntityRef instance
        private static DbRelatedEntityRef ConvertRelatedEntityRef(AST.RelshipNavigationExpr relshipExpr, SemanticResolver sr) 
        {
            //
            // Validate the relationship traversal
            // 
            DbExpression targetRef;
            RelationshipEndMember targetRefEnd; 
            RelationshipEndMember otherEnd; 
            RelationshipType relationshipType;
 
            ValidateRelationshipTraversal(relshipExpr,
                                          true /* targetEnd */ ,
                                          sr,
                                          out targetRef, 
                                          out relationshipType,
                                          out targetRefEnd, 
                                          out otherEnd); 

            // 
            // ensure is *..{0|1}
            //
            if (RelationshipMultiplicity.One != targetRefEnd.RelationshipMultiplicity &&
                RelationshipMultiplicity.ZeroOrOne != targetRefEnd.RelationshipMultiplicity) 
            {
                throw EntityUtil.EntitySqlError(relshipExpr.ErrCtx, 
                    Strings.InvalidWithRelationshipTargetEndMultiplicity(targetRefEnd.Identity, targetRefEnd.RelationshipMultiplicity.ToString())); 
            }
 
            DbRelatedEntityRef relatedEntityRef = DbExpressionBuilder.CreateRelatedEntityRef(otherEnd, targetRefEnd, targetRef);

            return relatedEntityRef;
        } 

        ///  
        /// Converts relationship navigation expression (AST.RelshipNavigationExpr) 
        /// 
        private static ExpressionResolution ConvertRelshipNavigationExpr(AST.Node astExpr, SemanticResolver sr) 
        {
            AST.RelshipNavigationExpr relshipExpr = (AST.RelshipNavigationExpr)astExpr;

            // 
            // Validate the relationship traversal
            // 
            DbExpression relationshipSource; 
            RelationshipEndMember fromEnd;
            RelationshipEndMember toEnd; 
            RelationshipType relationshipType;

            ValidateRelationshipTraversal(relshipExpr,
                                          false /* !targetEnd */, 
                                          sr,
                                          out relationshipSource, 
                                          out relationshipType, 
                                          out fromEnd,
                                          out toEnd); 

            //
            // create cqt expression
            // 
            DbExpression converted = relationshipSource.Navigate(fromEnd, toEnd);
            Debug.Assert(null != converted, "null != converted"); 
 
            return new ValueExpression(converted);
        } 

        /// 
        /// Converts REF expression (AST.RefExpr)
        ///  
        private static ExpressionResolution ConvertRefExpr(AST.Node astExpr, SemanticResolver sr)
        { 
            AST.RefExpr refExpr = (AST.RefExpr)astExpr; 

            DbExpression converted = ConvertValueExpression(refExpr.ArgExpr, sr); 

            //
            // check if is entity type
            // 
            if (!TypeSemantics.IsEntityType(converted.ResultType))
            { 
                throw EntityUtil.EntitySqlError(refExpr.ArgExpr.ErrCtx, Strings.RefArgIsNotOfEntityType(converted.ResultType.EdmType.FullName)); 
            }
 
            //
            // create ref expression
            //
            converted = converted.GetEntityRef(); 
            Debug.Assert(null != converted, "null != converted");
 
            return new ValueExpression(converted); 
        }
 
        /// 
        /// Converts DEREF expression (AST.DerefExpr)
        /// 
        private static ExpressionResolution ConvertDeRefExpr(AST.Node astExpr, SemanticResolver sr) 
        {
            AST.DerefExpr deRefExpr = (AST.DerefExpr)astExpr; 
 
            DbExpression converted = null;
 
            converted = ConvertValueExpression(deRefExpr.ArgExpr, sr);

            //
            // check if return type is RefType 
            //
            if (!TypeSemantics.IsReferenceType(converted.ResultType)) 
            { 
                throw EntityUtil.EntitySqlError(deRefExpr.ArgExpr.ErrCtx, Strings.DeRefArgIsNotOfRefType(converted.ResultType.EdmType.FullName));
            } 

            //
            // create DeRef expression
            // 
            converted = converted.Deref();
            Debug.Assert(null != converted, "null != converted"); 
 
            return new ValueExpression(converted);
        } 

        /// 
        /// Converts CREATEREF expression (AST.CreateRefExpr)
        ///  
        private static ExpressionResolution ConvertCreateRefExpr(AST.Node astExpr, SemanticResolver sr)
        { 
            AST.CreateRefExpr createRefExpr = (AST.CreateRefExpr)astExpr; 

            DbExpression converted = null; 

            //
            // Convert the entity set, also, ensure that we get back an extent expression
            // 
            DbScanExpression entitySetExpr = ConvertValueExpression(createRefExpr.EntitySet, sr) as DbScanExpression;
            if (entitySetExpr == null) 
            { 
                throw EntityUtil.EntitySqlError(createRefExpr.EntitySet.ErrCtx, Strings.ExprIsNotValidEntitySetForCreateRef);
            } 

            //
            // Ensure that the extent is an entity set
            // 
            EntitySet entitySet = entitySetExpr.Target as EntitySet;
            if (entitySet == null) 
            { 
                throw EntityUtil.EntitySqlError(createRefExpr.EntitySet.ErrCtx, Strings.ExprIsNotValidEntitySetForCreateRef);
            } 

            DbExpression keyRowExpression = ConvertValueExpression(createRefExpr.Keys, sr);

            ValidateIsNotUntypedNull(keyRowExpression, createRefExpr.Keys.ErrCtx); 

            RowType inputKeyRowType = keyRowExpression.ResultType.EdmType as RowType; 
            if (null == inputKeyRowType) 
            {
                throw EntityUtil.EntitySqlError(createRefExpr.Keys.ErrCtx, Strings.InvalidCreateRefKeyType); 
            }

            RowType entityKeyRowType = TypeHelpers.CreateKeyRowType(entitySet.ElementType);
 
            if (entityKeyRowType.Members.Count != inputKeyRowType.Members.Count)
            { 
                throw EntityUtil.EntitySqlError(createRefExpr.Keys.ErrCtx, Strings.ImcompatibleCreateRefKeyType); 
            }
 
            if (!TypeSemantics.IsStructurallyEqualOrPromotableTo(keyRowExpression.ResultType, TypeUsage.Create(entityKeyRowType)))
            {
                throw EntityUtil.EntitySqlError(createRefExpr.Keys.ErrCtx, Strings.ImcompatibleCreateRefKeyElementType);
            } 

            // 
            // if CREATEREF specifies a type, resolve and validate the type 
            //
            if (null != createRefExpr.TypeIdentifier) 
            {
                TypeUsage targetTypeUsage = ConvertTypeName(createRefExpr.TypeIdentifier, sr);

                // 
                // ensure type is entity
                // 
                if (!TypeSemantics.IsEntityType(targetTypeUsage)) 
                {
 
                    throw EntityUtil.EntitySqlError(createRefExpr.TypeIdentifier.ErrCtx,
                        Strings.CreateRefTypeIdentifierMustSpecifyAnEntityType(
                                                                    targetTypeUsage.EdmType.Identity,
                                                                    targetTypeUsage.EdmType.BuiltInTypeKind.ToString())); 
                }
 
                if (!TypeSemantics.IsValidPolymorphicCast(entitySet.ElementType, targetTypeUsage.EdmType)) 
                {
                    throw EntityUtil.EntitySqlError(createRefExpr.TypeIdentifier.ErrCtx, 
                        Strings.CreateRefTypeIdentifierMustBeASubOrSuperType(
                                                                    entitySet.ElementType.Identity,
                                                                    targetTypeUsage.EdmType.FullName));
                } 

                converted = DbExpressionBuilder.RefFromKey(entitySet, keyRowExpression, (EntityType)targetTypeUsage.EdmType); 
            } 
            else
            { 
                //
                // finally creates the expression
                //
                converted = DbExpressionBuilder.RefFromKey(entitySet, keyRowExpression); 
            }
 
            Debug.Assert(null != converted, "null != converted"); 

            return new ValueExpression(converted); 
        }

        /// 
        /// Validates the expression is typed.Throws  otherwise. 
        /// 
        private static void ValidateIsNotUntypedNull(DbExpression expression, ErrorContext errCtx) 
        { 
            if (expression is UntypedNullExpression)
            { 
                throw EntityUtil.EntitySqlError(errCtx, Strings.ExpressionCannotBeNull);
            }
        }
 
        /// 
        /// Converts KEY expression (AST.KeyExpr) 
        ///  
        private static ExpressionResolution ConvertKeyExpr(AST.Node astExpr, SemanticResolver sr)
        { 
            AST.KeyExpr keyExpr = (AST.KeyExpr)astExpr;

            DbExpression converted = ConvertValueExpression(keyExpr.ArgExpr, sr);
 
            ValidateIsNotUntypedNull(converted, keyExpr.ArgExpr.ErrCtx);
 
            if (TypeSemantics.IsEntityType(converted.ResultType)) 
            {
                converted = converted.GetEntityRef(); 
            }
            else if (!TypeSemantics.IsReferenceType(converted.ResultType))
            {
                throw EntityUtil.EntitySqlError(keyExpr.ArgExpr.ErrCtx, Strings.InvalidKeyArgument(TypeHelpers.GetFullName(converted.ResultType))); 
            }
 
            converted = converted.GetRefKey(); 
            Debug.Assert(null != converted, "null != converted");
 
            return new ValueExpression(converted);
        }

        ///  
        /// Converts a builtin expression (AST.BuiltInExpr).
        ///  
        private static ExpressionResolution ConvertBuiltIn(AST.Node astExpr, SemanticResolver sr) 
        {
            AST.BuiltInExpr bltInExpr = (AST.BuiltInExpr)astExpr; 

            BuiltInExprConverter builtInConverter = _builtInExprConverter[bltInExpr.Kind];
            if (builtInConverter == null)
            { 
                throw EntityUtil.EntitySqlError(Strings.UnknownBuiltInAstExpressionType);
            } 
 
            return new ValueExpression(builtInConverter(bltInExpr, sr));
        } 

        /// 
        /// Converts Arithmetic Expressions Args
        ///  
        /// 
        /// SemanticResolver instance relative to a especif typespace/system 
        ///  
        private static Pair ConvertArithmeticArgs(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr)
        { 
            DbExpression leftExpr = ConvertValueExpression(astBuiltInExpr.Arg1, sr);
            if (!(TypeSemantics.IsNumericType(leftExpr.ResultType) || IsUntypedNullExpression(leftExpr)))
            {
                throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.ExpressionMustBeNumericType); 
            }
 
            DbExpression rightExpr = null; 
            if (null != astBuiltInExpr.Arg2)
            { 
                rightExpr = ConvertValueExpression(astBuiltInExpr.Arg2, sr);

                if (!(TypeSemantics.IsNumericType(rightExpr.ResultType) || IsUntypedNullExpression(rightExpr)))
                { 
                    throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg2.ErrCtx, Strings.ExpressionMustBeNumericType);
                } 
 
                if (null == TypeHelpers.GetCommonTypeUsage(leftExpr.ResultType, rightExpr.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(astBuiltInExpr.ErrCtx, Strings.ArgumentTypesAreIncompatible(leftExpr.ResultType.EdmType.FullName, rightExpr.ResultType.EdmType.FullName));
                }
            }
 
            return ConvertUntypedNulls(leftExpr, rightExpr, astBuiltInExpr.ErrCtx, () => Strings.InvalidNullArithmetic);
        } 
 
        /// 
        /// Converts left and right s to typed null expressions. 
        /// Throws  if conversion is not possible.
        /// 
        private static Pair ConvertUntypedNulls(DbExpression leftExpr,
                                                                            DbExpression rightExpr, 
                                                                            ErrorContext errCtx,
                                                                            Func formatMessage) 
        { 
            DbExpression newLeftExpr = leftExpr;
            DbExpression newRightExpr = rightExpr; 
            UntypedNullExpression untypedLeftExpr = leftExpr as UntypedNullExpression;
            UntypedNullExpression untypedRightExpr = rightExpr as UntypedNullExpression;

            if (null != untypedLeftExpr) 
            {
                if (null != untypedRightExpr || null == rightExpr) 
                { 
                    throw EntityUtil.EntitySqlError(errCtx, formatMessage());
                } 
                else
                {
                    newLeftExpr = DbExpressionBuilder.Null(rightExpr.ResultType);
                } 
            }
            else if (null != untypedRightExpr) 
            { 
                newRightExpr = DbExpressionBuilder.Null(leftExpr.ResultType);
            } 

            return new Pair(newLeftExpr, newRightExpr);
        }
 
        /// 
        /// Converts Plus Args - specific case since string type is an allowed type for '+' 
        ///  
        /// 
        /// SemanticResolver instance relative to a especif typespace/system 
        /// 
        private static Pair ConvertPlusOperands(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr)
        {
            DbExpression leftExpr = ConvertValueExpression(astBuiltInExpr.Arg1, sr); 
            if (!(TypeSemantics.IsNumericType(leftExpr.ResultType) ||
                  TypeSemantics.IsPrimitiveType(leftExpr.ResultType, PrimitiveTypeKind.String) || 
                  IsUntypedNullExpression(leftExpr))) 
            {
                throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.PlusLeftExpressionInvalidType); 
            }

            DbExpression rightExpr = ConvertValueExpression(astBuiltInExpr.Arg2, sr);
            if (!(TypeSemantics.IsNumericType(rightExpr.ResultType) || 
                  TypeSemantics.IsPrimitiveType(rightExpr.ResultType, PrimitiveTypeKind.String) ||
                  IsUntypedNullExpression(rightExpr))) 
            { 
                throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg2.ErrCtx, Strings.PlusRightExpressionInvalidType);
            } 

            if (null == TypeHelpers.GetCommonTypeUsage(leftExpr.ResultType, rightExpr.ResultType))
            {
                throw EntityUtil.EntitySqlError(astBuiltInExpr.ErrCtx, Strings.ArgumentTypesAreIncompatible(leftExpr.ResultType.EdmType.FullName, rightExpr.ResultType.EdmType.FullName)); 
            }
 
            return ConvertUntypedNulls(leftExpr, rightExpr, astBuiltInExpr.ErrCtx, () => Strings.InvalidNullArithmetic); 
        }
 

        /// 
        /// Converts Logical Expression Args
        ///  
        /// 
        /// SemanticResolver instance relative to a especif typespace/system 
        ///  
        private static Pair ConvertLogicalArgs(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr)
        { 
            DbExpression leftExpr = ConvertValueExpression(astBuiltInExpr.Arg1, sr);
            if (leftExpr is UntypedNullExpression)
            {
                leftExpr = DbExpressionBuilder.Null(sr.TypeResolver.BooleanType); 
            }
 
            DbExpression rightExpr = null; 
            if (astBuiltInExpr.Arg2 != null)
            { 
                rightExpr = ConvertValueExpression(astBuiltInExpr.Arg2, sr);
                if (rightExpr is UntypedNullExpression)
                {
                    rightExpr = DbExpressionBuilder.Null(sr.TypeResolver.BooleanType); 
                }
            } 
 
            //
            // ensure left expression type is boolean 
            //
            if (!IsBooleanType(leftExpr.ResultType))
            {
                throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.ExpressionTypeMustBeBoolean); 
            }
 
            // 
            // ensure right expression type is boolean
            // 
            if (null != rightExpr && !IsBooleanType(rightExpr.ResultType))
            {
                throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg2.ErrCtx, Strings.ExpressionTypeMustBeBoolean);
            } 

            return new Pair(leftExpr, rightExpr); 
        } 

 
        /// 
        /// Converts Equal Comparison Expression Args
        /// 
        ///  
        /// SemanticResolver instance relative to a especif typespace/system
        ///  
        private static Pair ConvertEqualCompArgs(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr) 
        {
            // 
            // convert left and right types and infer null types
            //
            Pair compArgs = ConvertUntypedNulls(
                ConvertValueExpression(astBuiltInExpr.Arg1, sr), 
                ConvertValueExpression(astBuiltInExpr.Arg2, sr),
                astBuiltInExpr.ErrCtx, 
                () => Strings.InvalidNullComparison); 

            // 
            // ensure both operand types are equal-comparable
            //
            if (!TypeSemantics.IsEqualComparableTo(compArgs.Left.ResultType, compArgs.Right.ResultType))
            { 
                throw EntityUtil.EntitySqlError(astBuiltInExpr.ErrCtx, Strings.ArgumentTypesAreIncompatible(compArgs.Left.ResultType.EdmType.FullName, compArgs.Right.ResultType.EdmType.FullName));
            } 
 
            return compArgs;
        } 


        /// 
        /// Converts Order Comparison Expression Args 
        /// 
        ///  
        /// SemanticResolver instance relative to a especif typespace/system 
        /// 
        private static Pair ConvertOrderCompArgs(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr) 
        {
            Pair compArgs = ConvertUntypedNulls(
                ConvertValueExpression(astBuiltInExpr.Arg1, sr),
                ConvertValueExpression(astBuiltInExpr.Arg2, sr), 
                astBuiltInExpr.ErrCtx,
                () => Strings.InvalidNullComparison); 
 
            //
            // ensure both operand types are order-comparable 
            //
            if (!TypeSemantics.IsOrderComparableTo(compArgs.Left.ResultType, compArgs.Right.ResultType))
            {
                throw EntityUtil.EntitySqlError(astBuiltInExpr.ErrCtx, Strings.ArgumentTypesAreIncompatible(compArgs.Left.ResultType.EdmType.FullName, compArgs.Right.ResultType.EdmType.FullName)); 
            }
 
            return compArgs; 
        }
 

        /// 
        /// Converts Set Expression Args
        ///  
        /// 
        /// SemanticResolver instance relative to a especif typespace/system 
        ///  
        private static Pair ConvertSetArgs(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr)
        { 
            //
            // convert left expression
            //
            DbExpression leftExpr = ConvertValueExpression(astBuiltInExpr.Arg1, sr); 

            // 
            // convert right expression if binary set op kind 
            //
            DbExpression rightExpr = null; 
            if (null != astBuiltInExpr.Arg2)
            {
                //
                // binary set op 
                //
 
                // 
                // make sure left expression type is of sequence type (ICollection or Extent)
                // 
                if (!TypeSemantics.IsCollectionType(leftExpr.ResultType))
                {
                    throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.LeftSetExpressionArgsMustBeCollection);
                } 

                // 
                // convert right expression 
                //
                rightExpr = ConvertValueExpression(astBuiltInExpr.Arg2, sr); 

                //
                // make sure right expression type is of sequence type (ICollection or Extent)
                // 
                if (!TypeSemantics.IsCollectionType(rightExpr.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg2.ErrCtx, Strings.RightSetExpressionArgsMustBeCollection); 
                }
 
                TypeUsage commonType;
                TypeUsage leftElemType = TypeHelpers.GetElementTypeUsage(leftExpr.ResultType);
                TypeUsage rightElemType = TypeHelpers.GetElementTypeUsage(rightExpr.ResultType);
                if (!TypeSemantics.TryGetCommonType(leftElemType, rightElemType, out commonType)) 
                {
                    CqlErrorHelper.ReportIncompatibleCommonType(astBuiltInExpr.ErrCtx, leftElemType, rightElemType); 
                } 

                if (astBuiltInExpr.Kind != AST.BuiltInKind.UnionAll) 
                {
                    //
                    // ensure left argument is set op comparable
                    // 
                    if (!TypeHelpers.IsSetComparableOpType(TypeHelpers.GetElementTypeUsage(leftExpr.ResultType)))
                    { 
                        throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, 
                            Strings.PlaceholderSetArgTypeIsNotEqualComparable(
                                                           astBuiltInExpr.Kind.ToString().ToUpperInvariant(), 
                                                           Strings.LocalizedLeft,
                                                           TypeHelpers.GetElementTypeUsage(leftExpr.ResultType).EdmType.FullName));
                    }
 
                    //
                    // ensure right argument is set op comparable 
                    // 
                    if (!TypeHelpers.IsSetComparableOpType(TypeHelpers.GetElementTypeUsage(rightExpr.ResultType)))
                    { 
                        throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg2.ErrCtx,
                            Strings.PlaceholderSetArgTypeIsNotEqualComparable(
                                                           astBuiltInExpr.Kind.ToString().ToUpperInvariant(),
                                                           Strings.LocalizedRight, 
                                                           TypeHelpers.GetElementTypeUsage(rightExpr.ResultType).EdmType.FullName));
                    } 
                } 
                else
                { 
                    if (Helper.IsAssociationType(leftElemType.EdmType))
                    {
                        throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.InvalidAssociationTypeForUnion(leftElemType.Identity));
                    } 

                    if (Helper.IsAssociationType(rightElemType.EdmType)) 
                    { 
                        throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg2.ErrCtx, Strings.InvalidAssociationTypeForUnion(rightElemType.Identity));
                    } 
                }
            }
            else
            { 
                //
                // unary set op 
                // 

                // 
                // make sure expression type is of sequence type (ICollection or Extent)
                //
                if (!TypeSemantics.IsCollectionType(leftExpr.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.InvalidUnarySetOpArgument(astBuiltInExpr.Name));
                } 
 
                //
                // make sure that if is distinct unary operator, arg element type must be equal-comparable 
                //
                if (astBuiltInExpr.Kind == AST.BuiltInKind.Distinct && !TypeHelpers.IsValidDistinctOpType(TypeHelpers.GetElementTypeUsage(leftExpr.ResultType)))
                {
                    throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.ExpressionTypeMustBeEqualComparable); 
                }
            } 
 
            return new Pair(leftExpr, rightExpr);
        } 


        /// 
        /// Converts Set 'IN' expression args 
        /// 
        ///  
        /// SemanticResolver instance relative to a especif typespace/system 
        /// 
        private static Pair ConvertInExprArgs(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr) 
        {
            DbExpression leftExpr = ConvertValueExpression(astBuiltInExpr.Arg1, sr);
            if (TypeSemantics.IsCollectionType(leftExpr.ResultType))
            { 
                throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg1.ErrCtx, Strings.ExpressionTypeMustNotBeCollection);
            } 
 
            DbExpression rightExpr = ConvertValueExpression(astBuiltInExpr.Arg2, sr);
            if (!TypeSemantics.IsCollectionType(rightExpr.ResultType)) 
            {
                throw EntityUtil.EntitySqlError(astBuiltInExpr.Arg2.ErrCtx, Strings.RightSetExpressionArgsMustBeCollection);
            }
 
            //
            // if left expression type is null, infer its type from the collection element type 
            // 
            if (IsUntypedNullExpression(leftExpr))
            { 
                TypeUsage elementType = TypeHelpers.GetElementTypeUsage(rightExpr.ResultType);

                ValidateTypeForNullExpression(elementType, astBuiltInExpr.Arg1.ErrCtx);
 
                leftExpr = DbExpressionBuilder.Null(elementType);
            } 
            else 
            {
                // 
                // ensure that if left and right are typed expressions then their types must be comparable for IN op
                //
                TypeUsage commonElemType = TypeHelpers.GetCommonTypeUsage(leftExpr.ResultType, TypeHelpers.GetElementTypeUsage(rightExpr.ResultType));
                if (null == commonElemType || !TypeHelpers.IsValidInOpType(commonElemType)) 
                {
                    throw EntityUtil.EntitySqlError(astBuiltInExpr.ErrCtx, Strings.InvalidInExprArgs(leftExpr.ResultType.EdmType.FullName, rightExpr.ResultType.EdmType.FullName)); 
                } 
            }
 
            return new Pair(leftExpr, rightExpr);
        }

        private static void ValidateTypeForNullExpression(TypeUsage type, ErrorContext errCtx) 
        {
            if (TypeSemantics.IsCollectionType(type)) 
            { 
                throw EntityUtil.EntitySqlError(errCtx, Strings.NullLiteralCannotBePromotedToCollectionOfNulls);
            } 
        }

        /// 
        /// Converts Type Expression Args 
        /// 
        ///  
        /// SemanticResolver instance relative to a specific typespace/system 
        /// 
        private static Pair ConvertTypeExprArgs(AST.BuiltInExpr astBuiltInExpr, SemanticResolver sr) 
        {
            return new Pair(ConvertValueExpression(astBuiltInExpr.Arg1, sr), ConvertTypeName(astBuiltInExpr.Arg2, sr));
        }
 
        /// 
        /// Converts a type name. 
        /// Type name can be represented by 
        ///     - AST.Identifier, such as "Product"
        ///     - AST.DotExpr, such as "Northwind.Product" 
        ///     - AST.MethodExpr, such as "Edm.Decimal(10,4)", where "10" and "4" are type arguments.
        /// 
        private static TypeUsage ConvertTypeName(AST.Node typeName, SemanticResolver sr)
        { 
            Debug.Assert(typeName != null, "typeName != null");
 
            string[] name = null; 
            AST.NodeList typeSpecArgs = null;
 
            //
            // Process AST.MethodExpr - reduce it to an identifier with type spec arguments
            //
            AST.MethodExpr methodExpr = typeName as AST.MethodExpr; 
            if (methodExpr != null)
            { 
                typeName = methodExpr.Expr; 
                typeName.ErrCtx.ErrorContextInfo = methodExpr.ErrCtx.ErrorContextInfo;
                typeName.ErrCtx.UseContextInfoAsResourceIdentifier = methodExpr.ErrCtx.UseContextInfoAsResourceIdentifier; 

                typeSpecArgs = methodExpr.Args;
            }
 
            //
            // Try as AST.Identifier 
            // 
            AST.Identifier identifier = typeName as AST.Identifier;
            if (identifier != null) 
            {
                name = new string[] { identifier.Name };
            }
 
            //
            // Try as AST.DotExpr 
            // 
            AST.DotExpr dotExpr = typeName as AST.DotExpr;
            if (dotExpr != null && dotExpr.IsMultipartIdentifier(out name)) 
            {
                Debug.Assert(name != null, "name != null for a multipart identifier");
            }
 
            if (name == null)
            { 
                Debug.Fail("Unexpected AST.Node in the type name"); 
                throw EntityUtil.EntitySqlError(typeName.ErrCtx, Strings.InvalidMetadataMemberName);
            } 

            MetadataMember metadataMember = sr.ResolveMetadataMemberName(name, typeName.ErrCtx);
            Debug.Assert(metadataMember != null, "metadata member name resolution must not return null");
 
            switch (metadataMember.MetadataMemberClass)
            { 
                case MetadataMemberClass.Type: 
                    {
                        TypeUsage typeUsage = ((MetadataType)metadataMember).TypeUsage; 

                        if (typeSpecArgs != null)
                        {
                            typeUsage = ConvertTypeSpecArgs(typeUsage, typeSpecArgs, typeName.ErrCtx, sr); 
                        }
 
                        return typeUsage; 
                    }
 
                case MetadataMemberClass.FunctionGroup:
                case MetadataMemberClass.InlineFunctionGroup:
                    throw EntityUtil.EntitySqlError(typeName.ErrCtx, Strings.InvalidMetadataMemberClassResolution(
                        metadataMember.Name, metadataMember.MetadataMemberClassName, MetadataType.TypeClassName)); 

                default: 
                    throw EntityUtil.EntitySqlError(typeName.ErrCtx, Strings.TypeNameNotFound(metadataMember.Name)); 
            }
        } 

        private static TypeUsage ConvertTypeSpecArgs(TypeUsage parameterizedType, AST.NodeList typeSpecArgs, ErrorContext errCtx, SemanticResolver sr)
        {
            Debug.Assert(typeSpecArgs != null && typeSpecArgs.Count > 0, "typeSpecArgs must be null or a non-empty list"); 

            // 
            // Type arguments must be literals. 
            //
            foreach (AST.Node arg in typeSpecArgs) 
            {
                if (!(arg is AST.Literal))
                {
                    throw EntityUtil.EntitySqlError(arg.ErrCtx, Strings.TypeArgumentMustBeLiteral); 
                }
            } 
 
            //
            // The only parameterized type supported is Edm.Decimal 
            //
            PrimitiveType primitiveType = parameterizedType.EdmType as PrimitiveType;
            if (primitiveType == null || primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Decimal)
            { 
                throw EntityUtil.EntitySqlError(errCtx, Strings.TypeDoesNotSupportSpec(primitiveType.FullName));
            } 
 
            //
            // Edm.Decimal has two optional parameters: precision and scale. 
            //
            if (typeSpecArgs.Count > 2)
            {
                throw EntityUtil.EntitySqlError(errCtx, Strings.TypeArgumentCountMismatch(primitiveType.FullName, 2)); 
            }
 
            // 
            // Get precision value for Edm.Decimal
            // 
            byte precision;
            ConvertTypeFacetValue(primitiveType, (AST.Literal)typeSpecArgs[0], DbProviderManifest.PrecisionFacetName, out precision);

            // 
            // Get scale value for Edm.Decimal
            // 
            byte scale = 0; 
            if (typeSpecArgs.Count == 2)
            { 
                ConvertTypeFacetValue(primitiveType, (AST.Literal)typeSpecArgs[1], DbProviderManifest.ScaleFacetName, out scale);
            }

            // 
            // Ensure P >= S
            // 
            if (precision < scale) 
            {
                throw EntityUtil.EntitySqlError(typeSpecArgs[0].ErrCtx, Strings.PrecisionMustBeGreaterThanScale(precision, scale)); 
            }

            return TypeUsage.CreateDecimalTypeUsage(primitiveType, precision, scale);
        } 

        private static void ConvertTypeFacetValue(PrimitiveType type, AST.Literal value, string facetName, out byte byteValue) 
        { 
            FacetDescription facetDescription = Helper.GetFacet(type.ProviderManifest.GetFacetDescriptions(type), facetName);
            if (facetDescription == null) 
            {
                throw EntityUtil.EntitySqlError(value.ErrCtx, Strings.TypeDoesNotSupportFacet(type.FullName, facetName));
            }
 
            if (value.IsNumber && Byte.TryParse(value.OriginalValue, out byteValue))
            { 
                if (facetDescription.MaxValue.HasValue && byteValue > facetDescription.MaxValue.Value) 
                {
                    throw EntityUtil.EntitySqlError(value.ErrCtx, Strings.TypeArgumentExceedsMax(facetName)); 
                }

                if (facetDescription.MinValue.HasValue && byteValue < facetDescription.MinValue.Value)
                { 
                    throw EntityUtil.EntitySqlError(value.ErrCtx, Strings.TypeArgumentBelowMin(facetName));
                } 
            } 
            else
            { 
                throw EntityUtil.EntitySqlError(value.ErrCtx, Strings.TypeArgumentIsNotValid);
            }
        }
 
        private static TypeUsage ConvertTypeDefinition(AST.Node typeDefinitionExpr, SemanticResolver sr)
        { 
            Debug.Assert(typeDefinitionExpr != null, "typeDefinitionExpr != null"); 

            TypeUsage converted = null; 

            AST.CollectionTypeDefinition collTypeDefExpr = typeDefinitionExpr as AST.CollectionTypeDefinition;
            AST.RefTypeDefinition refTypeDefExpr = typeDefinitionExpr as AST.RefTypeDefinition;
            AST.RowTypeDefinition rowTypeDefExpr = typeDefinitionExpr as AST.RowTypeDefinition; 

            if (collTypeDefExpr != null) 
            { 
                TypeUsage elementType = ConvertTypeDefinition(collTypeDefExpr.ElementTypeDef, sr);
                converted = TypeHelpers.CreateCollectionTypeUsage(elementType, true /* readOnly */); 
            }
            else if (refTypeDefExpr != null)
            {
                TypeUsage targetTypeUsage = ConvertTypeName(refTypeDefExpr.RefTypeIdentifier, sr); 

                // 
                // Ensure type is entity 
                //
                if (!TypeSemantics.IsEntityType(targetTypeUsage)) 
                {

                    throw EntityUtil.EntitySqlError(refTypeDefExpr.RefTypeIdentifier.ErrCtx,
                        Strings.RefTypeIdentifierMustSpecifyAnEntityType( 
                                                    targetTypeUsage.EdmType.Identity,
                                                    targetTypeUsage.EdmType.BuiltInTypeKind.ToString())); 
                } 

                converted = TypeHelpers.CreateReferenceTypeUsage((EntityType)targetTypeUsage.EdmType); 
            }
            else if (rowTypeDefExpr != null)
            {
                Debug.Assert(rowTypeDefExpr.Properties != null && rowTypeDefExpr.Properties.Count > 0, "rowTypeDefExpr.Properties must be a non-empty collection"); 

                converted = TypeHelpers.CreateRowTypeUsage( 
                    rowTypeDefExpr.Properties.Select(p => new KeyValuePair(p.Name.Name, ConvertTypeDefinition(p.Type, sr))), 
                    true /* readOnly */);
            } 
            else
            {
                converted = ConvertTypeName(typeDefinitionExpr, sr);
            } 

            Debug.Assert(converted != null, "Type definition conversion yielded null"); 
 
            return converted;
        } 

        /// 
        /// Converts row constructor expression (AST.RowConstructorExpr)
        ///  
        private static ExpressionResolution ConvertRowConstructor(AST.Node expr, SemanticResolver sr)
        { 
            AST.RowConstructorExpr rowExpr = (AST.RowConstructorExpr)expr; 

            Dictionary rowColumns = new Dictionary(sr.StringComparer); 
            List fieldExprs = new List(rowExpr.AliasedExprList.Count);

            for (int i = 0; i < rowExpr.AliasedExprList.Count; i++)
            { 
                AST.AliasedExpr aliasExpr = rowExpr.AliasedExprList[i];
 
                DbExpression colExpr = ConvertValueExpression(aliasExpr.Expr, sr); 

                string aliasName = sr.InferAliasName(aliasExpr, colExpr); 

                if (rowColumns.ContainsKey(aliasName))
                {
                    if (aliasExpr.Alias != null) 
                    {
                        CqlErrorHelper.ReportAliasAlreadyUsedError(aliasName, aliasExpr.Alias.ErrCtx, Strings.InRowCtor); 
                    } 
                    else
                    { 
                        aliasName = sr.GenerateInternalName("autoRowCol");
                    }
                }
 
                if (IsUntypedNullExpression(colExpr))
                { 
                    throw EntityUtil.EntitySqlError(aliasExpr.Expr.ErrCtx, Strings.RowCtorElementCannotBeNull); 
                }
 
                rowColumns.Add(aliasName, colExpr.ResultType);

                fieldExprs.Add(colExpr);
            } 

            return new ValueExpression(DbExpressionBuilder.New(TypeHelpers.CreateRowTypeUsage(rowColumns, true /* readOnly */), fieldExprs)); 
        } 

        ///  
        /// Converts multiset constructor expression (AST.MultisetConstructorExpr)
        /// 
        private static ExpressionResolution ConvertMultisetConstructor(AST.Node expr, SemanticResolver sr)
        { 
            AST.MultisetConstructorExpr msetCtor = (AST.MultisetConstructorExpr)expr;
 
            if (null == msetCtor.ExprList) 
            {
                throw EntityUtil.EntitySqlError(expr.ErrCtx, Strings.CannotCreateEmptyMultiset); 
            }

            List mSetExprs = new List(msetCtor.ExprList.Select(e => ConvertValueExpression(e, sr)));
 
            TypeUsage commonType = TypeHelpers.GetCommonTypeUsage(mSetExprs.Select(e => e.ResultType));
 
            // 
            // ensure all elems have a common type
            // 
            if (null == commonType)
            {
                throw EntityUtil.EntitySqlError(expr.ErrCtx, Strings.MultisetElemsAreNotTypeCompatible);
            } 

            // 
            // ensure common type is not an untyped null 
            //
            if (TypeSemantics.IsNullType(commonType)) 
            {
                throw EntityUtil.EntitySqlError(expr.ErrCtx, Strings.CannotCreateMultisetofNulls);
            }
 
            commonType = TypeHelpers.GetReadOnlyType(commonType);
 
            // 
            // fixup untyped nulls
            // 
            for (int i = 0; i < mSetExprs.Count; i++)
            {
                if (IsUntypedNullExpression(mSetExprs[i]))
                { 
                    ValidateTypeForNullExpression(commonType, msetCtor.ExprList[i].ErrCtx);
 
                    mSetExprs[i] = DbExpressionBuilder.Null(commonType); 
                }
            } 

            return new ValueExpression(DbExpressionBuilder.New(TypeHelpers.CreateCollectionTypeUsage(commonType, true /* readOnly */), mSetExprs));
        }
 
        /// 
        /// Converts case-when-then expression (AST.CaseExpr) 
        ///  
        private static ExpressionResolution ConvertCaseExpr(AST.Node expr, SemanticResolver sr)
        { 
            AST.CaseExpr caseExpr = (AST.CaseExpr)expr;

            List whenExprList = new List(caseExpr.WhenThenExprList.Count);
            List thenExprList = new List(caseExpr.WhenThenExprList.Count); 

            // 
            // Convert when/then expressions. 
            //
            for (int i = 0; i < caseExpr.WhenThenExprList.Count; i++) 
            {
                AST.WhenThenExpr whenThenExpr = caseExpr.WhenThenExprList[i];

                DbExpression whenExpression = ConvertValueExpression(whenThenExpr.WhenExpr, sr); 

                if (!IsBooleanType(whenExpression.ResultType)) 
                { 
                    throw EntityUtil.EntitySqlError(whenThenExpr.WhenExpr.ErrCtx, Strings.ExpressionTypeMustBeBoolean);
                } 

                whenExprList.Add(whenExpression);

                DbExpression thenExpression = ConvertValueExpression(whenThenExpr.ThenExpr, sr); 

                thenExprList.Add(thenExpression); 
            } 

            TypeUsage resultType = TypeHelpers.GetCommonTypeUsage(thenExprList.Select(e => e.ResultType)); 
            if (null == resultType)
            {
                throw EntityUtil.EntitySqlError(caseExpr.WhenThenExprList[0].ThenExpr.ErrCtx, Strings.InvalidCaseThenTypes);
            } 

            if ((null == caseExpr.ElseExpr) && TypeSemantics.IsNullType(resultType)) 
            { 
                throw EntityUtil.EntitySqlError(caseExpr.WhenThenExprList[0].ThenExpr.ErrCtx, Strings.InvalidCaseThenNullType);
            } 

            //
            // Converts else if present
            // 
            DbExpression elseExpr = null;
            if (null != caseExpr.ElseExpr) 
            { 
                elseExpr = ConvertValueExpression(caseExpr.ElseExpr, sr);
 
                resultType = TypeHelpers.GetCommonTypeUsage(resultType, elseExpr.ResultType);
                if (null == resultType)
                {
                    throw EntityUtil.EntitySqlError(caseExpr.ElseExpr.ErrCtx, Strings.InvalidCaseElseType); 
                }
 
                if (TypeSemantics.IsNullType(resultType)) 
                {
                    throw EntityUtil.EntitySqlError(caseExpr.ElseExpr.ErrCtx, Strings.InvalidCaseWhenThenNullType); 
                }

                if (IsUntypedNullExpression(elseExpr))
                { 
                    ValidateTypeForNullExpression(resultType, caseExpr.ElseExpr.ErrCtx);
                    elseExpr = DbExpressionBuilder.Null(resultType); 
                } 
            }
            else 
            {
                if (TypeSemantics.IsCollectionType(resultType))
                {
                    elseExpr = DbExpressionBuilder.NewEmptyCollection(resultType); 
                }
                else 
                { 
                    ValidateTypeForNullExpression(resultType, caseExpr.ErrCtx);
                    elseExpr = DbExpressionBuilder.Null(resultType); 
                }
            }

            // 
            // fixup untyped nulls
            // 
            for (int i = 0; i < thenExprList.Count; i++) 
            {
                if (IsUntypedNullExpression(thenExprList[i])) 
                {
                    ValidateTypeForNullExpression(resultType, caseExpr.WhenThenExprList[i].ThenExpr.ErrCtx);

                    thenExprList[i] = DbExpressionBuilder.Null(resultType); 
                }
            } 
 
            return new ValueExpression(DbExpressionBuilder.Case(whenExprList, thenExprList, elseExpr));
        } 

        /// 
        /// Converts query expression (AST.QueryExpr)
        ///  
        private static ExpressionResolution ConvertQuery(AST.Node expr, SemanticResolver sr)
        { 
            AST.QueryExpr queryExpr = (AST.QueryExpr)expr; 

            DbExpression converted = null; 

            bool isRestrictedViewGenerationMode = (ParserOptions.CompilationMode.RestrictedViewGenerationMode == sr.ParserOptions.ParserCompilationMode);

            // 
            // Validate & Compensate Query
            // 
            ValidateAndCompensateQuery(queryExpr); 

            // 
            // Create Source Scope Region
            //
            using (sr.EnterScopeRegion())
            { 
                //
                // Process From Clause 
                // 
                DbExpressionBinding sourceExpr = ProcessFromClause(queryExpr.FromClause, sr);
 
                //
                // Process Where Clause
                //
                sourceExpr = ProcessWhereClause(sourceExpr, queryExpr.WhereClause, sr); 

                Debug.Assert(isRestrictedViewGenerationMode ? null == queryExpr.GroupByClause : true, "GROUP BY clause must be null in RestrictedViewGenerationMode"); 
                Debug.Assert(isRestrictedViewGenerationMode ? null == queryExpr.HavingClause : true, "HAVING clause must be null in RestrictedViewGenerationMode"); 
                Debug.Assert(isRestrictedViewGenerationMode ? null == queryExpr.OrderByClause : true, "ORDER BY clause must be null in RestrictedViewGenerationMode");
 
                bool queryProjectionProcessed = false;
                if (!isRestrictedViewGenerationMode)
                {
                    // 
                    // Process GroupBy Clause
                    // 
                    sourceExpr = ProcessGroupByClause(sourceExpr, queryExpr, sr); 

                    // 
                    // Process Having Clause
                    //
                    sourceExpr = ProcessHavingClause(sourceExpr, queryExpr.HavingClause, sr);
 
                    //
                    // Process OrderBy Clause 
                    // 
                    sourceExpr = ProcessOrderByClause(sourceExpr, queryExpr, out queryProjectionProcessed, sr);
                } 

                //
                // Process Projection Clause
                // 
                converted = ProcessSelectClause(sourceExpr, queryExpr, queryProjectionProcessed, sr);
 
            } // end query scope region 

            return new ValueExpression(converted); 
        }

        /// 
        /// Validates and Compensates query expression 
        /// 
        ///  
        private static void ValidateAndCompensateQuery(AST.QueryExpr queryExpr) 
        {
            if (null != queryExpr.HavingClause && null == queryExpr.GroupByClause) 
            {
                throw EntityUtil.EntitySqlError(queryExpr.ErrCtx, Strings.HavingRequiresGroupClause);
            }
 
            if (queryExpr.SelectClause.TopExpr != null)
            { 
                if (queryExpr.OrderByClause != null && queryExpr.OrderByClause.LimitSubClause != null) 
                {
                    throw EntityUtil.EntitySqlError(queryExpr.SelectClause.TopExpr.ErrCtx, Strings.TopAndLimitCannotCoexist); 
                }

                if (queryExpr.OrderByClause != null && queryExpr.OrderByClause.SkipSubClause != null)
                { 
                    throw EntityUtil.EntitySqlError(queryExpr.SelectClause.TopExpr.ErrCtx, Strings.TopAndSkipCannotCoexist);
                } 
            } 
        }
 
        /// 
        /// Process Select Clause
        /// 
        private static DbExpression ProcessSelectClause(DbExpressionBinding source, AST.QueryExpr queryExpr, bool queryProjectionProcessed, SemanticResolver sr) 
        {
            AST.SelectClause selectClause = queryExpr.SelectClause; 
 
            DbExpression projectExpression;
            if (queryProjectionProcessed) 
            {
                projectExpression = source.Expression;
            }
            else 
            {
                // 
                // Convert projection items. 
                //
                var projectionItems = ConvertSelectClauseItems(queryExpr, sr); 

                //
                // Create project expression off the projectionItems.
                // 
                projectExpression = CreateProjectExpression(source, selectClause, projectionItems);
            } 
 
            //
            // Handle TOP/LIMIT sub-clauses. 
            //
            if (selectClause.TopExpr != null || (queryExpr.OrderByClause != null && queryExpr.OrderByClause.LimitSubClause != null))
            {
                AST.Node limitExpr; 
                string exprName;
                if (selectClause.TopExpr != null) 
                { 
                    limitExpr = selectClause.TopExpr;
                    exprName =  "TOP"; 
                }
                else
                {
                    limitExpr = queryExpr.OrderByClause.LimitSubClause; 
                    exprName = "LIMIT";
                } 
 
                //
                // Convert the expression. 
                //
                DbExpression convertedLimit = ConvertValueExpression(limitExpr, sr);

                // 
                // Ensure expression is typed.
                // 
                ValidateIsNotUntypedNull(convertedLimit, limitExpr.ErrCtx); 

                // 
                // Ensure the converted expression is in the range of values.
                //
                ValidateExpressionIsCommandParamOrNonNegativeIntegerConstant(convertedLimit, limitExpr.ErrCtx, exprName, sr);
 
                //
                // Create the project expression with the limit. 
                // 
                projectExpression = projectExpression.Limit(convertedLimit);
            } 

            Debug.Assert(null != projectExpression, "null != projectExpression");
            return projectExpression;
        } 

        private static List> ConvertSelectClauseItems(AST.QueryExpr queryExpr, SemanticResolver sr) 
        { 
            AST.SelectClause selectClause = queryExpr.SelectClause;
 
            //
            // Validate SELECT VALUE projection list.
            //
            if (selectClause.SelectKind == AST.SelectKind.Value) 
            {
                if (selectClause.Items.Count != 1) 
                { 
                    throw EntityUtil.EntitySqlError(selectClause.ErrCtx, Strings.InvalidSelectValueList);
                } 

                //
                // Aliasing is not allowed in the SELECT VALUE case.
                // 
                if (selectClause.Items[0].Alias != null)
                { 
                    throw EntityUtil.EntitySqlError(selectClause.Items[0].ErrCtx, Strings.InvalidSelectValueAliasedExpression); 
                }
            } 

            //
            // Converts projection list
            // 
            HashSet projectionAliases = new HashSet(sr.StringComparer);
            List> projectionItems = new List>(selectClause.Items.Count); 
            for (int i = 0; i < selectClause.Items.Count; i++) 
            {
                AST.AliasedExpr projectionItem = selectClause.Items[i]; 

                DbExpression converted = ConvertValueExpression(projectionItem.Expr, sr);

                // 
                // Ensure expression is typed.
                // 
                ValidateIsNotUntypedNull(converted, projectionItem.Expr.ErrCtx); 

                // 
                // Infer projection item alias.
                //
                string aliasName = sr.InferAliasName(projectionItem, converted);
 
                //
                // Ensure the alias is not already used. 
                // 
                if (projectionAliases.Contains(aliasName))
                { 
                    if (projectionItem.Alias != null)
                    {
                        CqlErrorHelper.ReportAliasAlreadyUsedError(aliasName, projectionItem.Alias.ErrCtx, Strings.InSelectProjectionList);
                    } 
                    else
                    { 
                        aliasName = sr.GenerateInternalName("autoProject"); 
                    }
                } 

                projectionAliases.Add(aliasName);
                projectionItems.Add(new KeyValuePair(aliasName, converted));
            } 

            Debug.Assert(projectionItems.Count > 0, "projectionItems.Count > 0"); 
            return projectionItems; 
        }
 
        private static DbExpression CreateProjectExpression(DbExpressionBinding source, AST.SelectClause selectClause, List> projectionItems)
        {
            //
            // Create DbProjectExpression off the projectionItems. 
            //
            DbExpression projectExpression; 
            if (selectClause.SelectKind == AST.SelectKind.Value) 
            {
                Debug.Assert(projectionItems.Count == 1, "projectionItems.Count must be 1 for SELECT VALUE"); 
                projectExpression = source.Project(projectionItems[0].Value);
            }
            else
            { 
                projectExpression = source.Project(DbExpressionBuilder.NewRow(projectionItems));
            } 
 
            //
            // Handle DISTINCT modifier - create DbDistinctExpression over the current projectExpression. 
            //
            if (selectClause.DistinctKind == AST.DistinctKind.Distinct)
            {
                // 
                // Ensure element type is equal-comparable.
                // 
                ValidateDistinctProjection(projectExpression.ResultType, selectClause); 

                // 
                // Create distinct expression.
                //
                projectExpression = projectExpression.Distinct();
            } 

            return projectExpression; 
        } 

        private static void ValidateDistinctProjection(TypeUsage projectExpressionResultType, AST.SelectClause selectClause) 
        {
            ValidateDistinctProjection(
                projectExpressionResultType,
                selectClause.Items[0].Expr.ErrCtx, 
                selectClause.SelectKind == System.Data.Common.EntitySql.AST.SelectKind.Row ?
                    new List(selectClause.Items.Select(item => item.Expr.ErrCtx)) : null); 
        } 

        private static void ValidateDistinctProjection(TypeUsage projectExpressionResultType, ErrorContext defaultErrCtx, List projectionItemErrCtxs) 
        {
            TypeUsage projectionType = TypeHelpers.GetElementTypeUsage(projectExpressionResultType);
            if (!TypeHelpers.IsValidDistinctOpType(projectionType))
            { 
                ErrorContext errCtx = defaultErrCtx;
                if (projectionItemErrCtxs != null && TypeSemantics.IsRowType(projectionType)) 
                { 
                    RowType rowType = projectionType.EdmType as RowType;
                    Debug.Assert(projectionItemErrCtxs.Count == rowType.Members.Count); 
                    for (int i = 0; i < rowType.Members.Count; i++)
                    {
                        if (!TypeHelpers.IsValidDistinctOpType(rowType.Members[i].TypeUsage))
                        { 
                            errCtx = projectionItemErrCtxs[i];
                            break; 
                        } 
                    }
                } 
                throw EntityUtil.EntitySqlError(errCtx, Strings.SelectDistinctMustBeEqualComparable);
            }
        }
 
        private static void ValidateExpressionIsCommandParamOrNonNegativeIntegerConstant(DbExpression expr, ErrorContext errCtx, string exprName, SemanticResolver sr)
        { 
            if (expr.ExpressionKind != DbExpressionKind.Constant && 
                expr.ExpressionKind != DbExpressionKind.ParameterReference)
            { 
                throw EntityUtil.EntitySqlError(errCtx, Strings.PlaceholderExpressionMustBeConstant(exprName));
            }

            if (!TypeSemantics.IsPromotableTo(expr.ResultType, sr.TypeResolver.Int64Type)) 
            {
                throw EntityUtil.EntitySqlError(errCtx, Strings.PlaceholderExpressionMustBeCompatibleWithEdm64(exprName, TypeHelpers.GetFullName(expr.ResultType))); 
            } 

            DbConstantExpression constExpr = expr as DbConstantExpression; 
            if (constExpr!= null && System.Convert.ToInt64(constExpr.Value, CultureInfo.InvariantCulture) < 0)
            {
                throw EntityUtil.EntitySqlError(errCtx, Strings.PlaceholderExpressionMustBeGreaterThanOrEqualToZero(exprName));
            } 
        }
 
        ///  
        /// Process FROM clause.
        ///  
        private static DbExpressionBinding ProcessFromClause(AST.FromClause fromClause, SemanticResolver sr)
        {
            DbExpressionBinding fromBinding = null;
 
            //
            // Process each FROM clause item. 
            // If there is more than one of them, then assemble them in a string from APPLYs. 
            //
            List fromClauseEntries = new List(); 
            for (int i = 0; i < fromClause.FromClauseItems.Count; i++)
            {
                //
                // Convert FROM clause item. 
                //
                List fromClauseItemEntries; 
                DbExpressionBinding currentItemBinding = ProcessFromClauseItem(fromClause.FromClauseItems[i], sr, out fromClauseItemEntries); 
                fromClauseEntries.AddRange(fromClauseItemEntries);
 
                if (fromBinding == null)
                {
                    fromBinding = currentItemBinding;
                } 
                else
                { 
                    fromBinding = fromBinding.CrossApply(currentItemBinding).BindAs(sr.GenerateInternalName("lcapply")); 

                    // 
                    // Adjust scope entries with the new binding.
                    //
                    fromClauseEntries.ForEach(scopeEntry => scopeEntry.AddParentVar(fromBinding.Variable));
                } 
            }
 
            Debug.Assert(fromBinding != null, "fromBinding != null"); 

            return fromBinding; 
        }

        /// 
        /// Process generic FROM clause item: aliasedExpr, JoinClauseItem or ApplyClauseItem. 
        /// Returns  and the  list with entries created by the clause item.
        ///  
        private static DbExpressionBinding ProcessFromClauseItem(AST.FromClauseItem fromClauseItem, SemanticResolver sr, out List scopeEntries) 
        {
            DbExpressionBinding fromItemBinding = null; 

            switch (fromClauseItem.FromClauseItemKind)
            {
                case AST.FromClauseItemKind.AliasedFromClause: 
                    fromItemBinding = ProcessAliasedFromClauseItem((AST.AliasedExpr)fromClauseItem.FromExpr, sr, out scopeEntries);
                    break; 
 
                case AST.FromClauseItemKind.JoinFromClause:
                    fromItemBinding = ProcessJoinClauseItem((AST.JoinClauseItem)fromClauseItem.FromExpr, sr, out scopeEntries); 
                    break;

                default:
                    Debug.Assert(fromClauseItem.FromClauseItemKind == AST.FromClauseItemKind.ApplyFromClause, "AST.FromClauseItemKind.ApplyFromClause expected"); 
                    fromItemBinding = ProcessApplyClauseItem((AST.ApplyClauseItem)fromClauseItem.FromExpr, sr, out scopeEntries);
                    break; 
            } 

            Debug.Assert(fromItemBinding != null, "fromItemBinding != null"); 

            return fromItemBinding;
        }
 
        /// 
        /// Process a simple FROM clause item. 
        /// Returns  and the  list with a single entry created for the clause item. 
        /// 
        private static DbExpressionBinding ProcessAliasedFromClauseItem(AST.AliasedExpr aliasedExpr, SemanticResolver sr, out List scopeEntries) 
        {
            DbExpressionBinding aliasedBinding = null;

            // 
            // Convert the item expression.
            // 
            DbExpression converted = ConvertValueExpression(aliasedExpr.Expr, sr); 

            // 
            // Ensure expression is typed.
            //
            ValidateIsNotUntypedNull(converted, aliasedExpr.Expr.ErrCtx);
 
            //
            // Validate it is of collection type. 
            // 
            if (!TypeSemantics.IsCollectionType(converted.ResultType))
            { 
                throw EntityUtil.EntitySqlError(aliasedExpr.Expr.ErrCtx, Strings.ExpressionMustBeCollection);
            }

            // 
            // Infer source var alias name.
            // 
            string aliasName = sr.InferAliasName(aliasedExpr, converted); 

            // 
            // Validate the name was not used yet.
            //
            if (sr.CurrentScope.Contains(aliasName))
            { 
                if (aliasedExpr.Alias != null)
                { 
                    CqlErrorHelper.ReportAliasAlreadyUsedError(aliasName, aliasedExpr.Alias.ErrCtx, Strings.InFromClause); 
                }
                else 
                {
                    aliasName = sr.GenerateInternalName("autoFrom");
                }
            } 

            // 
            // Create CQT expression. 
            //
            aliasedBinding = converted.BindAs(aliasName); 

            //
            // Add source var to the _scopeEntries list and to the current scope.
            // 
            SourceScopeEntry sourceScopeEntry = new SourceScopeEntry(aliasedBinding.Variable);
            sr.CurrentScope.Add(aliasedBinding.Variable.VariableName, sourceScopeEntry); 
            scopeEntries = new List(); 
            scopeEntries.Add(sourceScopeEntry);
 
            Debug.Assert(aliasedBinding != null, "aliasedBinding != null");

            return aliasedBinding;
        } 

        ///  
        /// Process a JOIN clause item. 
        /// Returns  and the  list with a join-left and join-right entries created for the clause item.
        ///  
        private static DbExpressionBinding ProcessJoinClauseItem(AST.JoinClauseItem joinClause, SemanticResolver sr, out List scopeEntries)
        {
            DbExpressionBinding joinBinding = null;
 
            //
            // Make sure inner join has ON predicate AND cross join has no ON predicate. 
            // 
            if (null == joinClause.OnExpr)
            { 
                if (AST.JoinKind.Inner == joinClause.JoinKind)
                {
                    throw EntityUtil.EntitySqlError(joinClause.ErrCtx, Strings.InnerJoinMustHaveOnPredicate);
                } 
            }
            else 
            { 
                if (AST.JoinKind.Cross == joinClause.JoinKind)
                { 
                    throw EntityUtil.EntitySqlError(joinClause.OnExpr.ErrCtx, Strings.InvalidPredicateForCrossJoin);
                }
            }
 
            //
            // Process left expression. 
            // 
            List leftExprScopeEntries;
            DbExpressionBinding leftBindingExpr = ProcessFromClauseItem(joinClause.LeftExpr, sr, out leftExprScopeEntries); 

            //
            // Mark scope entries from the left expression as such. This will disallow their usage inside of the right expression.
            // The left and right expressions of a join must be independent (they can not refer to variables in the other expression). 
            // Join ON predicate may refer to variables defined in both expressions.
            // Examples: 
            //     Select ... From A JOIN B JOIN A.x             -> invalid 
            //     Select ... From A JOIN B JOIN C ON A.x = C.x  -> valid
            //     Select ... From A JOIN B, C JOIN A.x ...      -> valid 
            //
            leftExprScopeEntries.ForEach(scopeEntry => scopeEntry.IsJoinClauseLeftExpr = true);

            // 
            // Process right expression
            // 
            List rightExprScopeEntries; 
            DbExpressionBinding rightBindingExpr = ProcessFromClauseItem(joinClause.RightExpr, sr, out rightExprScopeEntries);
 
            //
            // Unmark scope entries from the left expression to allow their usage.
            //
            leftExprScopeEntries.ForEach(scopeEntry => scopeEntry.IsJoinClauseLeftExpr = false); 

 
            // 
            // Switch right outer to left outer.
            // 
            if (joinClause.JoinKind == AST.JoinKind.RightOuter)
            {
                joinClause.JoinKind = AST.JoinKind.LeftOuter;
                DbExpressionBinding tmpExpr = leftBindingExpr; 
                leftBindingExpr = rightBindingExpr;
                rightBindingExpr = tmpExpr; 
            } 

            // 
            // Resolve JoinType.
            //
            DbExpressionKind joinKind = MapJoinKind(joinClause.JoinKind);
 
            //
            // Resolve ON. 
            // 
            DbExpression onExpr = null;
            if (null == joinClause.OnExpr) 
            {
                if (DbExpressionKind.CrossJoin != joinKind)
                {
                    onExpr = DbExpressionBuilder.True; 
                }
            } 
            else 
            {
                onExpr = ConvertValueExpression(joinClause.OnExpr, sr); 

                //
                // Ensure expression is typed.
                // 
                ValidateIsNotUntypedNull(onExpr, joinClause.OnExpr.ErrCtx);
            } 
 
            //
            // Create New Join 
            //
            joinBinding =
                DbExpressionBuilder.CreateJoinExpressionByKind(
                    joinKind, onExpr, leftBindingExpr, rightBindingExpr).BindAs(sr.GenerateInternalName("join")); 

            // 
            // Combine left and right scope entries and adjust with the new binding. 
            //
            scopeEntries = leftExprScopeEntries; 
            scopeEntries.AddRange(rightExprScopeEntries);
            scopeEntries.ForEach(scopeEntry => scopeEntry.AddParentVar(joinBinding.Variable));

            Debug.Assert(joinBinding != null, "joinBinding != null"); 

            return joinBinding; 
        } 

        ///  
        /// Maps  to .
        /// 
        private static DbExpressionKind MapJoinKind(AST.JoinKind joinKind)
        { 
            Debug.Assert(joinKind != AST.JoinKind.RightOuter, "joinKind != JoinKind.RightOuter");
            return joinMap[(int)joinKind]; 
        } 
        private static readonly DbExpressionKind[] joinMap = { DbExpressionKind.CrossJoin, DbExpressionKind.InnerJoin, DbExpressionKind.LeftOuterJoin, DbExpressionKind.FullOuterJoin };
 
        /// 
        /// Process an APPLY clause item.
        /// Returns  and the  list with an apply-left and apply-right entries created for the clause item.
        ///  
        private static DbExpressionBinding ProcessApplyClauseItem(AST.ApplyClauseItem applyClause, SemanticResolver sr, out List scopeEntries)
        { 
            DbExpressionBinding applyBinding = null; 

            // 
            // Resolve left expression.
            //
            List leftExprScopeEntries;
            DbExpressionBinding leftBindingExpr = ProcessFromClauseItem(applyClause.LeftExpr, sr, out leftExprScopeEntries); 

            // 
            // Resolve right expression. 
            //
            List rightExprScopeEntries; 
            DbExpressionBinding rightBindingExpr = ProcessFromClauseItem(applyClause.RightExpr, sr, out rightExprScopeEntries);

            //
            // Create Apply. 
            //
            applyBinding = 
                DbExpressionBuilder.CreateApplyExpressionByKind( 
                    MapApplyKind(applyClause.ApplyKind),
                    leftBindingExpr, 
                    rightBindingExpr).BindAs(sr.GenerateInternalName("apply"));

            //
            // Combine left and right scope entries and adjust with the new binding. 
            //
            scopeEntries = leftExprScopeEntries; 
            scopeEntries.AddRange(rightExprScopeEntries); 
            scopeEntries.ForEach(scopeEntry => scopeEntry.AddParentVar(applyBinding.Variable));
 
            Debug.Assert(applyBinding != null, "applyBinding != null");

            return applyBinding;
        } 

        ///  
        /// Maps  to . 
        /// 
        private static DbExpressionKind MapApplyKind(AST.ApplyKind applyKind) 
        {
            return applyMap[(int)applyKind];
        }
        private static readonly DbExpressionKind[] applyMap = { DbExpressionKind.CrossApply, DbExpressionKind.OuterApply }; 

        ///  
        /// Process WHERE clause. 
        /// 
        private static DbExpressionBinding ProcessWhereClause(DbExpressionBinding source, AST.Node whereClause, SemanticResolver sr) 
        {
            if (whereClause == null)
            {
                return source; 
            }
            return ProcessWhereHavingClausePredicate(source, whereClause, whereClause.ErrCtx, "where", sr); 
        } 

        ///  
        /// Process HAVING clause.
        /// 
        private static DbExpressionBinding ProcessHavingClause(DbExpressionBinding source, AST.HavingClause havingClause, SemanticResolver sr)
        { 
            if (havingClause == null)
            { 
                return source; 
            }
            return ProcessWhereHavingClausePredicate(source, havingClause.HavingPredicate, havingClause.ErrCtx, "having", sr); 
        }

        /// 
        /// Process WHERE or HAVING clause predicate. 
        /// 
        private static DbExpressionBinding ProcessWhereHavingClausePredicate(DbExpressionBinding source, AST.Node predicate, ErrorContext errCtx, string bindingNameTemplate, SemanticResolver sr) 
        { 
            Debug.Assert(predicate != null, "predicate != null");
 
            DbExpressionBinding whereBinding = null;

            //
            // Convert the predicate. 
            //
            DbExpression filterConditionExpr = ConvertValueExpression(predicate, sr); 
 
            //
            // Ensure expression is typed. 
            //
            ValidateIsNotUntypedNull(filterConditionExpr, errCtx);

            // 
            // Ensure the predicate type is boolean.
            // 
            if (!IsBooleanType(filterConditionExpr.ResultType)) 
            {
                throw EntityUtil.EntitySqlError(errCtx, Strings.ExpressionTypeMustBeBoolean); 
            }

            //
            // Create new filter binding. 
            //
            whereBinding = source.Filter(filterConditionExpr).BindAs(sr.GenerateInternalName(bindingNameTemplate)); 
 
            //
            // Fixup Bindings. 
            //
            sr.CurrentScopeRegion.ApplyToScopeEntries(scopeEntry =>
            {
                Debug.Assert(scopeEntry.EntryKind == ScopeEntryKind.SourceVar || scopeEntry.EntryKind == ScopeEntryKind.InvalidGroupInputRef, 
                    "scopeEntry.EntryKind == ScopeEntryKind.SourceVar || scopeEntry.EntryKind == ScopeEntryKind.InvalidGroupInputRef");
 
                if (scopeEntry.EntryKind == ScopeEntryKind.SourceVar) 
                {
                    ((SourceScopeEntry)scopeEntry).ReplaceParentVar(whereBinding.Variable); 
                }
            });

            Debug.Assert(whereBinding != null, "whereBinding != null"); 

            return whereBinding; 
        } 

        ///  
        /// Process Group By Clause
        /// 
        private static DbExpressionBinding ProcessGroupByClause(DbExpressionBinding source, AST.QueryExpr queryExpr, SemanticResolver sr)
        { 
            AST.GroupByClause groupByClause = queryExpr.GroupByClause;
 
            Debug.Assert((sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode) ? null == groupByClause : true, "GROUP BY clause must be null in RestrictedViewGenerationMode"); 

            // 
            // If group expression is null, assume an implicit group and speculate that there are group aggregates in the remaining query expression.
            // If no group aggregate are found after partial evaluation of HAVING, ORDER BY and SELECT, rollback the implicit group.
            //
            int groupKeysCount = groupByClause != null ? groupByClause.GroupItems.Count : 0; 
            bool isImplicitGroup = groupKeysCount == 0;
            if (isImplicitGroup && !queryExpr.HasMethodCall) 
            { 
                return source;
            } 

            //
            // Create input binding for DbGroupByExpression.
            // 
            DbGroupExpressionBinding groupInputBinding = source.Expression.GroupBindAs(sr.GenerateInternalName("geb"), sr.GenerateInternalName("group"));
 
            // 
            // Create group partition (DbGroupAggregate) and projection template.
            // 
            DbGroupAggregate groupAggregateDefinition = groupInputBinding.GroupAggregate;
            DbVariableReferenceExpression groupAggregateVarRef = groupAggregateDefinition.ResultType.Variable(sr.GenerateInternalName("groupAggregate"));
            DbExpressionBinding groupAggregateBinding = groupAggregateVarRef.BindAs(sr.GenerateInternalName("groupPartitionItem"));
 
            //
            // Flag that we perform group operation. 
            // 
            sr.CurrentScopeRegion.EnterGroupOperation(groupAggregateBinding);
 
            //
            // Update group input bindings.
            //
            sr.CurrentScopeRegion.ApplyToScopeEntries((scopeEntry) => 
            {
                Debug.Assert(scopeEntry.EntryKind == ScopeEntryKind.SourceVar, "scopeEntry.EntryKind == ScopeEntryKind.SourceVar"); 
                ((SourceScopeEntry)scopeEntry).AdjustToGroupVar(groupInputBinding.Variable, groupInputBinding.GroupVariable, groupAggregateBinding.Variable); 
            });
 
            //
            // This set will include names of keys, aggregates and the group partition name if specified.
            // All these properties become field names of the row type returned by the DbGroupByExpression.
            // 
            HashSet groupPropertyNames = new HashSet(sr.StringComparer);
 
            // 
            // Convert group keys.
            // 
            #region Convert group key definitions
            List groupKeys = new List(groupKeysCount);
            if (!isImplicitGroup)
            { 
                Debug.Assert(null != groupByClause, "groupByClause must not be null at this point");
                for (int i = 0; i < groupKeysCount; i++) 
                { 
                    AST.AliasedExpr aliasedExpr = groupByClause.GroupItems[i];
 
                    sr.CurrentScopeRegion.WasResolutionCorrelated = false;

                    //
                    // Convert key expression relative to groupInputBinding.Variable. 
                    // This expression will be used as key definition during construction of DbGroupByExpression.
                    // 
                    DbExpression keyExpr; 
                    GroupKeyAggregateInfo groupKeyAggregateInfo;
                    using (sr.EnterGroupKeyDefinition(GroupAggregateKind.GroupKey, aliasedExpr.ErrCtx, out groupKeyAggregateInfo)) 
                    {
                        keyExpr = ConvertValueExpression(aliasedExpr.Expr, sr);
                    }
 
                    //
                    // Ensure expression is typed. 
                    // 
                    ValidateIsNotUntypedNull(keyExpr, aliasedExpr.Expr.ErrCtx);
 
                    //
                    // Ensure group key expression is correlated.
                    // If resolution was correlated, then the following should be true for groupKeyAggregateInfo: ESR == DSR
                    // 
                    if (!sr.CurrentScopeRegion.WasResolutionCorrelated)
                    { 
                        throw EntityUtil.EntitySqlError(aliasedExpr.Expr.ErrCtx, Strings.KeyMustBeCorrelated("GROUP BY")); 
                    }
                    Debug.Assert(groupKeyAggregateInfo.EvaluatingScopeRegion == groupKeyAggregateInfo.DefiningScopeRegion, "Group key must evaluate on the scope it was defined on."); 

                    //
                    // Ensure key is valid.
                    // 
                    if (!TypeHelpers.IsValidGroupKeyType(keyExpr.ResultType))
                    { 
                        throw EntityUtil.EntitySqlError(aliasedExpr.Expr.ErrCtx, Strings.GroupingKeysMustBeEqualComparable); 
                    }
 
                    //
                    // Convert key expression relative to groupInputBinding.GroupVariable.
                    // keyExprForFunctionAggregates will be used inside of definitions of group aggregates resolved to the current scope region.
                    // 
                    DbExpression keyExprForFunctionAggregates;
                    GroupKeyAggregateInfo functionAggregateInfo; 
                    using (sr.EnterGroupKeyDefinition(GroupAggregateKind.Function, aliasedExpr.ErrCtx, out functionAggregateInfo)) 
                    {
                        keyExprForFunctionAggregates = ConvertValueExpression(aliasedExpr.Expr, sr); 
                    }
                    Debug.Assert(functionAggregateInfo.EvaluatingScopeRegion == functionAggregateInfo.DefiningScopeRegion, "Group key must evaluate on the scope it was defined on.");

                    // 
                    // Convert key expression relative to groupAggregateBinding.Variable.
                    // keyExprForGroupPartitions will be used inside of definitions of GROUPPARTITION aggregates resolved to the current scope region. 
                    // 
                    DbExpression keyExprForGroupPartitions;
                    GroupKeyAggregateInfo groupPartitionInfo; 
                    using (sr.EnterGroupKeyDefinition(GroupAggregateKind.Partition, aliasedExpr.ErrCtx, out groupPartitionInfo))
                    {
                        keyExprForGroupPartitions = ConvertValueExpression(aliasedExpr.Expr, sr);
                    } 
                    Debug.Assert(groupPartitionInfo.EvaluatingScopeRegion == groupPartitionInfo.DefiningScopeRegion, "Group key must evaluate on the scope it was defined on.");
 
                    // 
                    // Infer group key alias name.
                    // 
                    string groupKeyAlias = sr.InferAliasName(aliasedExpr, keyExpr);

                    //
                    // Check if alias was already used. 
                    //
                    if (groupPropertyNames.Contains(groupKeyAlias)) 
                    { 
                        if (aliasedExpr.Alias != null)
                        { 
                            CqlErrorHelper.ReportAliasAlreadyUsedError(groupKeyAlias, aliasedExpr.Alias.ErrCtx, Strings.InGroupClause);
                        }
                        else
                        { 
                            groupKeyAlias = sr.GenerateInternalName("autoGroup");
                        } 
                    } 

                    // 
                    // Add alias to dictionary.
                    //
                    groupPropertyNames.Add(groupKeyAlias);
 
                    //
                    // Add key to keys collection. 
                    // 
                    GroupKeyInfo groupKeyInfo = new GroupKeyInfo(groupKeyAlias, keyExpr, keyExprForFunctionAggregates, keyExprForGroupPartitions);
                    groupKeys.Add(groupKeyInfo); 

                    //
                    // Group keys should be visible by their 'original' key expression name. The following three forms should be allowed:
                    //   SELECT k       FROM ... as p GROUP BY p.Price as k (explicit key alias) - handled above by InferAliasName() 
                    //   SELECT Price   FROM ... as p GROUP BY p.Price      (implicit alias - leading name) - handled above by InferAliasName()
                    //   SELECT p.Price FROM ... as p GROUP BY p.Price      (original key expression) - case handled in the code bellow 
                    // 
                    if (aliasedExpr.Alias == null)
                    { 
                        AST.DotExpr dotExpr = aliasedExpr.Expr as AST.DotExpr;
                        string[] alternativeName;
                        if (null != dotExpr && dotExpr.IsMultipartIdentifier(out alternativeName))
                        { 
                            groupKeyInfo.AlternativeName = alternativeName;
 
                            string alternativeFullName = TypeResolver.GetFullName(alternativeName); 
                            if (groupPropertyNames.Contains(alternativeFullName))
                            { 
                                CqlErrorHelper.ReportAliasAlreadyUsedError(alternativeFullName, dotExpr.ErrCtx, Strings.InGroupClause);
                            }

                            groupPropertyNames.Add(alternativeFullName); 
                        }
                    } 
                } 
            }
            #endregion 

            //
            // Save scope. It will be used to rollback the temporary group scope created below.
            // 
            int groupInputScope = sr.CurrentScopeIndex;
 
            // 
            // Push temporary group scope.
            // 
            sr.EnterScope();

            //
            // Add scope entries for group keys and the group partition to the current scope, 
            // this is needed for the aggregate search phase during which keys may be referenced.
            // 
            foreach (GroupKeyInfo groupKeyInfo in groupKeys) 
            {
                sr.CurrentScope.Add( 
                    groupKeyInfo.Name,
                    new GroupKeyDefinitionScopeEntry(
                        groupKeyInfo.VarBasedKeyExpr,
                        groupKeyInfo.GroupVarBasedKeyExpr, 
                        groupKeyInfo.GroupAggBasedKeyExpr,
                        null)); 
 
                if (groupKeyInfo.AlternativeName != null)
                { 
                    string strAlternativeName = TypeResolver.GetFullName(groupKeyInfo.AlternativeName);
                    sr.CurrentScope.Add(
                        strAlternativeName,
                        new GroupKeyDefinitionScopeEntry( 
                            groupKeyInfo.VarBasedKeyExpr,
                            groupKeyInfo.GroupVarBasedKeyExpr, 
                            groupKeyInfo.GroupAggBasedKeyExpr, 
                            groupKeyInfo.AlternativeName));
                } 
            }

            //
            // Convert/Search Aggregates 
            // since aggregates can be defined in Having, OrderBy and/or Select clauses must be resolved as part of the group expression.
            // The resolution of these clauses result in potential collection of resolved group aggregates and the actual resulting 
            // expression is ignored. These clauses will be then resolved as usual on a second pass. 
            //
 
            #region Search for group aggregates (functions and GROUPPARTITIONs)
            //
            // Search for aggregates in HAVING clause.
            // 
            if (null != queryExpr.HavingClause && queryExpr.HavingClause.HasMethodCall)
            { 
                DbExpression converted = ConvertValueExpression(queryExpr.HavingClause.HavingPredicate, sr); 

                // 
                // Ensure expression is typed.
                //
                ValidateIsNotUntypedNull(converted, queryExpr.HavingClause.ErrCtx);
            } 

            // 
            // Search for aggregates in SELECT clause. 
            //
            Dictionary projectionExpressions = null; 
            if (null != queryExpr.OrderByClause || queryExpr.SelectClause.HasMethodCall)
            {
                projectionExpressions = new Dictionary(queryExpr.SelectClause.Items.Count, sr.StringComparer);
                for (int i = 0; i < queryExpr.SelectClause.Items.Count; i++) 
                {
                    AST.AliasedExpr aliasedExpr = queryExpr.SelectClause.Items[i]; 
 
                    //
                    // Convert projection item expression. 
                    //
                    DbExpression converted = ConvertValueExpression(aliasedExpr.Expr, sr);

                    // 
                    // Ensure expression is typed.
                    // 
                    ValidateIsNotUntypedNull(converted, aliasedExpr.Expr.ErrCtx); 

                    // 
                    // Create Null Expression with actual type.
                    //
                    converted = converted.ExpressionKind == CommandTrees.DbExpressionKind.Null ? converted : converted.ResultType.Null();
 
                    //
                    // Infer alias. 
                    // 
                    string aliasName = sr.InferAliasName(aliasedExpr, converted);
 
                    if (projectionExpressions.ContainsKey(aliasName))
                    {
                        if (aliasedExpr.Alias != null)
                        { 
                            CqlErrorHelper.ReportAliasAlreadyUsedError(aliasName,
                                                                       aliasedExpr.Alias.ErrCtx, 
                                                                       Strings.InSelectProjectionList); 
                        }
                        else 
                        {
                            aliasName = sr.GenerateInternalName("autoProject");
                        }
                    } 

                    projectionExpressions.Add(aliasName, converted); 
                } 
            }
 
            //
            // Search for aggregates in ORDER BY clause.
            //
            if (null != queryExpr.OrderByClause && queryExpr.OrderByClause.HasMethodCall) 
            {
                // 
                // Push temporary projection scope. 
                //
                sr.EnterScope(); 

                //
                // Add projection items to the temporary scope (items may be used in ORDER BY).
                // 
                foreach (KeyValuePair kvp in projectionExpressions)
                { 
                    sr.CurrentScope.Add(kvp.Key, new ProjectionItemDefinitionScopeEntry(kvp.Value)); 
                }
 
                //
                // Search for aggregates in ORDER BY clause.
                //
                for (int i = 0; i < queryExpr.OrderByClause.OrderByClauseItem.Count; i++) 
                {
                    AST.OrderByClauseItem orderItem = queryExpr.OrderByClause.OrderByClauseItem[i]; 
 
                    sr.CurrentScopeRegion.WasResolutionCorrelated = false;
 
                    DbExpression converted = ConvertValueExpression(orderItem.OrderExpr, sr);

                    //
                    // Ensure expression is typed. 
                    //
                    ValidateIsNotUntypedNull(converted, orderItem.OrderExpr.ErrCtx); 
 
                    //
                    // Ensure key expression is correlated. 
                    //
                    if (!sr.CurrentScopeRegion.WasResolutionCorrelated)
                    {
                        throw EntityUtil.EntitySqlError(orderItem.ErrCtx, Strings.KeyMustBeCorrelated("ORDER BY")); 
                    }
                } 
 
                //
                // Pop temporary projection scope. 
                //
                sr.LeaveScope();
            }
            #endregion 

            // 
            // If we introduced a fake group but did not find any group aggregates 
            // on the first pass, then there is no need for creating an implicit group.
            // Rollback to the status before entering ProcessGroupByClause(). 
            // If we did find group aggregates, make sure all non-group aggregate function
            // expressions refer to group scope variables only.
            //
            if (isImplicitGroup) 
            {
                if (0 == sr.CurrentScopeRegion.GroupAggregateInfos.Count) 
                { 
                    #region Implicit Group Rollback
                    // 
                    // Rollback the temporary group scope.
                    //
                    sr.RollbackToScope(groupInputScope);
 
                    //
                    // Undo any group source fixups: re-applying the source var and remove the group var. 
                    // 
                    sr.CurrentScopeRegion.ApplyToScopeEntries((scopeEntry) =>
                    { 
                        Debug.Assert(scopeEntry.EntryKind == ScopeEntryKind.SourceVar, "scopeEntry.EntryKind == ScopeEntryKind.SourceVar");
                        ((SourceScopeEntry)scopeEntry).RollbackAdjustmentToGroupVar(source.Variable);
                    });
 
                    //
                    // Remove the group operation flag. 
                    // 
                    sr.CurrentScopeRegion.RollbackGroupOperation();
                    #endregion 
                    //
                    // Return the original source var binding.
                    //
                    return source; 
                }
            } 
 
            //
            // Prepare list of aggregate definitions and their internal names. 
            //
            List> aggregates = new List>(sr.CurrentScopeRegion.GroupAggregateInfos.Count);
            bool groupPartitionRefFound = false;
            foreach (GroupAggregateInfo groupAggregateInfo in sr.CurrentScopeRegion.GroupAggregateInfos) 
            {
                switch (groupAggregateInfo.AggregateKind) 
                { 
                    case GroupAggregateKind.Function:
                        aggregates.Add(new KeyValuePair( 
                            groupAggregateInfo.AggregateName,
                            ((FunctionAggregateInfo)groupAggregateInfo).AggregateDefinition));
                        break;
 
                    case GroupAggregateKind.Partition:
                        groupPartitionRefFound = true; 
                        break; 

                    default: 
                        Debug.Fail("Unexpected group aggregate kind:" + groupAggregateInfo.AggregateKind.ToString());
                        break;
                }
            } 
            if (groupPartitionRefFound)
            { 
                // 
                // Add DbAggregate to support GROUPPARTITION definitions.
                // 
                aggregates.Add(new KeyValuePair(groupAggregateVarRef.VariableName, groupAggregateDefinition));
            }

            // 
            // Create GroupByExpression and a binding to it.
            // 
            DbGroupByExpression groupBy = groupInputBinding.GroupBy( 
                groupKeys.Select(keyInfo => new KeyValuePair(keyInfo.Name, keyInfo.VarBasedKeyExpr)),
                aggregates); 
            DbExpressionBinding groupBinding = groupBy.BindAs(sr.GenerateInternalName("group"));

            //
            // If there are GROUPPARTITION expressions, then add an extra projection off the groupBinding to 
            //  - project all the keys and aggregates, except the DbGroupAggregate,
            //  - project definitions of GROUPPARTITION expressions. 
            // 
            if (groupPartitionRefFound)
            { 
                //
                // All GROUPPARTITION definitions reference groupAggregateVarRef, make sure the variable is properly defined in the groupBy expression.
                //
                Debug.Assert(aggregates.Any((aggregate) => String.CompareOrdinal(aggregate.Key, groupAggregateVarRef.VariableName) == 0), 
                    "DbAggregate is not defined");
 
                // 
                // Get projection of GROUPPARTITION definitions.
                // This method may return null if all GROUPPARTITION definitions are reduced to the value of groupAggregateVarRef. 
                //
                List> projectionItems = ProcessGroupPartitionDefinitions(
                    sr.CurrentScopeRegion.GroupAggregateInfos,
                    groupAggregateVarRef, 
                    groupBinding);
 
                if (projectionItems != null) 
                {
                    // 
                    // Project group keys along with GROUPPARTITION definitions.
                    //
                    projectionItems.AddRange(groupKeys.Select(keyInfo =>
                        new KeyValuePair(keyInfo.Name, groupBinding.Variable.Property(keyInfo.Name)))); 

                    // 
                    // Project function group aggregates along with GROUPPARTITION definitions and group keys. 
                    //
                    projectionItems.AddRange(sr.CurrentScopeRegion.GroupAggregateInfos 
                        .Where(groupAggregateInfo => groupAggregateInfo.AggregateKind == GroupAggregateKind.Function)
                        .Select(groupAggregateInfo => new KeyValuePair(
                            groupAggregateInfo.AggregateName,
                            groupBinding.Variable.Property(groupAggregateInfo.AggregateName)))); 

                    DbExpression projectExpression = DbExpressionBuilder.NewRow(projectionItems); 
                    groupBinding = groupBinding.Project(projectExpression).BindAs(sr.GenerateInternalName("groupPartitionDefs")); 
                }
            } 

            //
            // Remove the temporary group scope with group key definitions,
            // Replace all existing pre-group scope entries with InvalidGroupInputRefScopeEntry stubs - 
            // they are no longer available for proper referencing and only to be used for user error messages.
            // 
            sr.RollbackToScope(groupInputScope); 
            sr.CurrentScopeRegion.ApplyToScopeEntries((scopeEntry) =>
            { 
                Debug.Assert(scopeEntry.EntryKind == ScopeEntryKind.SourceVar, "scopeEntry.EntryKind == ScopeEntryKind.SourceVar");
                return new InvalidGroupInputRefScopeEntry();
            });
 
            //
            // Add final group scope. 
            // 
            sr.EnterScope();
 
            //
            // Add group keys to the group scope.
            //
            foreach (GroupKeyInfo groupKeyInfo in groupKeys) 
            {
                // 
                // Add new scope entry 
                //
                sr.CurrentScope.Add( 
                    groupKeyInfo.VarRef.VariableName,
                    new SourceScopeEntry(groupKeyInfo.VarRef).AddParentVar(groupBinding.Variable));

                // 
                // Handle the alternative name entry.
                // 
                if (groupKeyInfo.AlternativeName != null) 
                {
                    // 
                    // We want two scope entries with keys as groupKeyInfo.VarRef.VariableName and groupKeyInfo.AlternativeName,
                    // both pointing to the same variable (groupKeyInfo.VarRef).
                    //
                    string strAlternativeName = TypeResolver.GetFullName(groupKeyInfo.AlternativeName); 
                    sr.CurrentScope.Add(
                        strAlternativeName, 
                        new SourceScopeEntry(groupKeyInfo.VarRef, groupKeyInfo.AlternativeName).AddParentVar(groupBinding.Variable)); 
                }
            } 

            //
            // Add group aggregates to the scope.
            // 
            foreach (GroupAggregateInfo groupAggregateInfo in sr.CurrentScopeRegion.GroupAggregateInfos)
            { 
                DbVariableReferenceExpression aggVarRef = groupAggregateInfo.AggregateStubExpression.ResultType.Variable(groupAggregateInfo.AggregateName); 

                Debug.Assert( 
                    !sr.CurrentScope.Contains(aggVarRef.VariableName) ||
                    groupAggregateInfo.AggregateKind == GroupAggregateKind.Partition, "DbFunctionAggregate's with duplicate names are not allowed.");

                if (!sr.CurrentScope.Contains(aggVarRef.VariableName)) 
                {
                    sr.CurrentScope.Add( 
                        aggVarRef.VariableName, 
                        new SourceScopeEntry(aggVarRef).AddParentVar(groupBinding.Variable));
                    sr.CurrentScopeRegion.RegisterGroupAggregateName(aggVarRef.VariableName); 
                }

                //
                // Cleanup the stub expression as it must not be used after this point. 
                //
                groupAggregateInfo.AggregateStubExpression = null; 
            } 

            return groupBinding; 
        }

        /// 
        /// Generates the list of projections for GROUPPARTITION definitions. 
        /// All GROUPPARTITION definitions over the trivial projection of input are reduced to the value of groupAggregateVarRef,
        /// only one projection item is created for such definitions. 
        /// Returns null if all GROUPPARTITION definitions are reduced to the value of groupAggregateVarRef. 
        /// 
        private static List> ProcessGroupPartitionDefinitions( 
            List groupAggregateInfos,
            DbVariableReferenceExpression groupAggregateVarRef,
            DbExpressionBinding groupBinding)
        { 
            var gpExpressionLambdaVariables = new System.Collections.ObjectModel.ReadOnlyCollection(
                new DbVariableReferenceExpression[] { groupAggregateVarRef }); 
 
            List> groupPartitionDefinitions = new List>();
            bool foundTrivialGroupAggregateProjection = false; 
            foreach (GroupAggregateInfo groupAggregateInfo in groupAggregateInfos)
            {
                if (groupAggregateInfo.AggregateKind == GroupAggregateKind.Partition)
                { 
                    DbExpression aggregateDefinition = ((GroupPartitionInfo)groupAggregateInfo).AggregateDefinition;
                    if (IsTrivialInputProjection(groupAggregateVarRef, aggregateDefinition)) 
                    { 
                        //
                        // Reduce the case of the trivial projection of input to the value of groupAggregateVarRef. 
                        //
                        groupAggregateInfo.AggregateName = groupAggregateVarRef.VariableName;
                        foundTrivialGroupAggregateProjection = true;
                    } 
                    else
                    { 
                        // 
                        // Build a projection item for the non-trivial definition.
                        // 
                        DbLambda gpExpressionLambda = new DbLambda(gpExpressionLambdaVariables, ((GroupPartitionInfo)groupAggregateInfo).AggregateDefinition);
                        groupPartitionDefinitions.Add(new KeyValuePair(
                            groupAggregateInfo.AggregateName,
                            gpExpressionLambda.Invoke(groupBinding.Variable.Property(groupAggregateVarRef.VariableName)))); 
                    }
                } 
            } 

            if (foundTrivialGroupAggregateProjection) 
            {
                if (groupPartitionDefinitions.Count > 0)
                {
                    // 
                    // Add projection item for groupAggregateVarRef if there are reduced definitions.
                    // 
                    groupPartitionDefinitions.Add(new KeyValuePair( 
                        groupAggregateVarRef.VariableName,
                        groupBinding.Variable.Property(groupAggregateVarRef.VariableName))); 
                }
                else
                {
                    // 
                    // If all GROUPPARTITION definitions have been reduced, return null.
                    // In this case the wrapping projection will not be created and 
                    // groupAggregateVarRef will be projected directly from the DbGroupByExpression. 
                    //
                    groupPartitionDefinitions = null; 
                }
            }

            return groupPartitionDefinitions; 
        }
 
        ///  
        /// Returns true if lambda accepts a collection variable and trivially projects out its elements.
        ///  
        private static bool IsTrivialInputProjection(DbVariableReferenceExpression lambdaVariable, DbExpression lambdaBody)
        {
            if (lambdaBody.ExpressionKind != DbExpressionKind.Project)
            { 
                return false;
            } 
            DbProjectExpression projectExpression = (DbProjectExpression)lambdaBody; 

            if (projectExpression.Input.Expression != lambdaVariable) 
            {
                return false;
            }
 
            Debug.Assert(TypeSemantics.IsCollectionType(lambdaVariable.ResultType));
 
            if (projectExpression.Projection.ExpressionKind == DbExpressionKind.VariableReference) 
            {
                DbVariableReferenceExpression projectionExpression = (DbVariableReferenceExpression)projectExpression.Projection; 
                return projectionExpression == projectExpression.Input.Variable;
            }
            else if (projectExpression.Projection.ExpressionKind == DbExpressionKind.NewInstance &&
                     TypeSemantics.IsRowType(projectExpression.Projection.ResultType)) 
            {
                if (!TypeSemantics.IsEqual(projectExpression.Projection.ResultType, projectExpression.Input.Variable.ResultType)) 
                { 
                    return false;
                } 

                IBaseList inputVariableTypeProperties = TypeHelpers.GetAllStructuralMembers(projectExpression.Input.Variable.ResultType);

                DbNewInstanceExpression projectionExpression = (DbNewInstanceExpression)projectExpression.Projection; 

                Debug.Assert(projectionExpression.Arguments.Count == inputVariableTypeProperties.Count, "projectionExpression.Arguments.Count == inputVariableTypeProperties.Count"); 
                for (int i = 0; i < projectionExpression.Arguments.Count; ++i) 
                {
                    if (projectionExpression.Arguments[i].ExpressionKind != DbExpressionKind.Property) 
                    {
                        return false;
                    }
                    DbPropertyExpression propertyRef = (DbPropertyExpression)projectionExpression.Arguments[i]; 

                    if (propertyRef.Instance != projectExpression.Input.Variable || 
                        propertyRef.Property != inputVariableTypeProperties[i]) 
                    {
                        return false; 
                    }
                }

                return true; 
            }
 
            return false; 
        }
 
        private sealed class GroupKeyInfo
        {
            internal GroupKeyInfo(string name, DbExpression varBasedKeyExpr, DbExpression groupVarBasedKeyExpr, DbExpression groupAggBasedKeyExpr)
            { 
                Name = name;
                VarRef = varBasedKeyExpr.ResultType.Variable(name); 
                VarBasedKeyExpr = varBasedKeyExpr; 
                GroupVarBasedKeyExpr = groupVarBasedKeyExpr;
                GroupAggBasedKeyExpr = groupAggBasedKeyExpr; 
            }

            /// 
            /// The primary name of the group key. It is used to refer to the key from other expressions. 
            /// 
            internal readonly string Name; 
 
            /// 
            /// Optional alternative name of the group key. 
            /// Used to support the following scenario:
            ///   SELECT Price, p.Price   FROM ... as p GROUP BY p.Price
            /// In this case the group key Name is "Price" and the AlternativeName is "p.Price" as if it is coming as an escaped identifier.
            ///  
            internal string[] AlternativeName
            { 
                get { return _alternativeName; } 
                set
                { 
                    Debug.Assert(_alternativeName == null, "GroupKeyInfo.AlternativeName can not be reset");
                    _alternativeName = value;
                }
            } 
            private string[] _alternativeName;
 
            internal readonly DbVariableReferenceExpression VarRef; 

            internal readonly DbExpression VarBasedKeyExpr; 

            internal readonly DbExpression GroupVarBasedKeyExpr;

            internal readonly DbExpression GroupAggBasedKeyExpr; 
        }
 
        ///  
        /// Process ORDER BY clause.
        ///  
        private static DbExpressionBinding ProcessOrderByClause(DbExpressionBinding source, AST.QueryExpr queryExpr, out bool queryProjectionProcessed, SemanticResolver sr)
        {
            Debug.Assert((sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode) ? null == queryExpr.OrderByClause : true, "ORDER BY clause must be null in RestrictedViewGenerationMode");
 
            queryProjectionProcessed = false;
 
            if (queryExpr.OrderByClause == null) 
            {
                return source; 
            }

            DbExpressionBinding sortBinding = null;
            AST.OrderByClause orderByClause = queryExpr.OrderByClause; 
            AST.SelectClause selectClause = queryExpr.SelectClause;
 
            // 
            // Convert SKIP sub-clause if exists before adding projection expressions to the scope.
            // 
            DbExpression convertedSkip = null;
            #region
            if (orderByClause.SkipSubClause != null)
            { 
                //
                // Convert the skip expression. 
                // 
                convertedSkip = ConvertValueExpression(orderByClause.SkipSubClause, sr);
 
                //
                // Ensure expression is typed.
                //
                ValidateIsNotUntypedNull(convertedSkip, orderByClause.SkipSubClause.ErrCtx); 

                // 
                // Ensure the converted expression is in the range of values. 
                //
                ValidateExpressionIsCommandParamOrNonNegativeIntegerConstant(convertedSkip, orderByClause.SkipSubClause.ErrCtx, "SKIP", sr); 
            }
            #endregion

            // 
            // Convert SELECT clause items before processing the rest of the ORDER BY clause:
            //      - If it is the SELECT DISTINCT case: 
            //          SELECT clause item definitions will be used to create DbDistinctExpression, which becomes the new source expression. 
            //          Sort keys can only reference:
            //              a. SELECT clause items by their aliases (only these aliases are projected by the new source expression), 
            //              b. entries from outer scopes.
            //      - Otherwise:
            //          Sort keys may references any available scope entries, including SELECT clause items.
            //          If a sort key references a SELECT clause item, the item _definition_ will be used as the sort key definition (not a variable ref). 
            //
            var projectionItems = ConvertSelectClauseItems(queryExpr, sr); 
 
            if (selectClause.DistinctKind == AST.DistinctKind.Distinct)
            { 
                //
                // SELECT DISTINCT ... ORDER BY case:
                //      - All scope entries created below SELECT DISTINCT are not valid above it in this query, even for error messages, so remove them.
                //      - The scope entries created by SELECT DISTINCT (the SELECT clause items) will be added to a temporary scope in the code below, 
                //        this will make them available for sort keys.
                // 
                sr.CurrentScopeRegion.RollbackAllScopes(); 
            }
 
            //
            // Create temporary scope for SELECT clause items and add the items to the scope.
            //
            int savedScope = sr.CurrentScopeIndex; 
            sr.EnterScope();
            projectionItems.ForEach(projectionItem => sr.CurrentScope.Add(projectionItem.Key, new ProjectionItemDefinitionScopeEntry(projectionItem.Value))); 
 
            //
            // Process SELECT DISTINCT ... ORDER BY case: 
            //      - create projection expression: new Row(SELECT clause item defintions) or just the single SELECT clause item defintion;
            //      - create DbDistinctExpression over the projection expression;
            //      - set source expression to the binding to the distinct.
            // 
            if (selectClause.DistinctKind == AST.DistinctKind.Distinct)
            { 
                // 
                // Create distinct projection expression and bind to it.
                // 
                DbExpression projectExpression = CreateProjectExpression(source, selectClause, projectionItems);
                Debug.Assert(projectExpression is DbDistinctExpression, "projectExpression is DbDistinctExpression");
                source = projectExpression.BindAs(sr.GenerateInternalName("distinct"));
 
                //
                // Replace SELECT clause item definitions with regular source scope entries pointing into the new source binding. 
                // 
                if (selectClause.SelectKind == AST.SelectKind.Value)
                { 
                    Debug.Assert(projectionItems.Count == 1, "projectionItems.Count == 1");
                    sr.CurrentScope.Replace(projectionItems[0].Key, new SourceScopeEntry(source.Variable));
                }
                else 
                {
                    Debug.Assert(selectClause.SelectKind == AST.SelectKind.Row, "selectClause.SelectKind == AST.SelectKind.Row"); 
                    foreach (var projectionExpression in projectionItems) 
                    {
                        DbVariableReferenceExpression projectionExpressionRef = projectionExpression.Value.ResultType.Variable(projectionExpression.Key); 

                        sr.CurrentScope.Replace(projectionExpressionRef.VariableName,
                            new SourceScopeEntry(projectionExpressionRef).AddParentVar(source.Variable));
                    } 
                }
 
                // 
                // At this point source contains all projected items, so query processing is mostly complete,
                // the only task remaining is processing of TOP/LIMIT subclauses, which happens in ProcessSelectClause(...) method. 
                //
                queryProjectionProcessed = true;
            }
 
            //
            // Convert sort keys. 
            // 
            List sortKeys = new List(orderByClause.OrderByClauseItem.Count);
            #region 
            for (int i = 0; i < orderByClause.OrderByClauseItem.Count; i++)
            {
                AST.OrderByClauseItem orderClauseItem = orderByClause.OrderByClauseItem[i];
 
                sr.CurrentScopeRegion.WasResolutionCorrelated = false;
 
                // 
                // Convert order key expression.
                // 
                DbExpression keyExpr = ConvertValueExpression(orderClauseItem.OrderExpr, sr);

                //
                // Ensure expression is typed. 
                //
                ValidateIsNotUntypedNull(keyExpr, orderClauseItem.OrderExpr.ErrCtx); 
 
                //
                // Ensure key expression is correlated. 
                //
                if (!sr.CurrentScopeRegion.WasResolutionCorrelated)
                {
                    throw EntityUtil.EntitySqlError(orderClauseItem.ErrCtx, Strings.KeyMustBeCorrelated("ORDER BY")); 
                }
 
                // 
                // Ensure key is order comparable.
                // 
                if (!TypeHelpers.IsValidSortOpKeyType(keyExpr.ResultType))
                {
                    throw EntityUtil.EntitySqlError(orderClauseItem.OrderExpr.ErrCtx, Strings.OrderByKeyIsNotOrderComparable);
                } 

                // 
                // Convert order direction. 
                //
                bool ascSort = (orderClauseItem.OrderKind == AST.OrderKind.None) || (orderClauseItem.OrderKind == AST.OrderKind.Asc); 

                //
                // Convert collation.
                // 
                string collation = null;
                if (orderClauseItem.Collation != null) 
                { 
                    if (!IsStringType(keyExpr.ResultType))
                    { 
                        throw EntityUtil.EntitySqlError(orderClauseItem.OrderExpr.ErrCtx, Strings.InvalidKeyTypeForCollation(keyExpr.ResultType.EdmType.FullName));
                    }

                    collation = orderClauseItem.Collation.Name; 
                }
 
                // 
                // Finish key conversion and add converted keys to key collection.
                // 
                if (string.IsNullOrEmpty(collation))
                {
                    sortKeys.Add(ascSort ? keyExpr.ToSortClause() : keyExpr.ToSortClauseDescending());
                } 
                else
                { 
                    sortKeys.Add(ascSort ? keyExpr.ToSortClause(collation) : keyExpr.ToSortClauseDescending(collation)); 
                }
            } 
            #endregion

            //
            // Remove the temporary projection scope with all the SELECT clause items on it. 
            //
            sr.RollbackToScope(savedScope); 
 
            //
            // Create sort expression. 
            //
            DbExpression sortSourceExpr = null;
            if (convertedSkip != null)
            { 
                sortSourceExpr = source.Skip(sortKeys, convertedSkip);
            } 
            else 
            {
                sortSourceExpr = source.Sort(sortKeys); 
            }

            //
            // Create Sort Binding. 
            //
            sortBinding = sortSourceExpr.BindAs(sr.GenerateInternalName("sort")); 
 
            //
            // Fixup Bindings. 
            //
            if (queryProjectionProcessed)
            {
                Debug.Assert(sr.CurrentScopeIndex < sr.CurrentScopeRegion.FirstScopeIndex, "Current scope region is expected to have no scopes."); 

                /* 
                 * The following code illustrates definition of the projected output in the case of DISTINCT ORDER BY. 
                 * There is nothing above this point that should reference any scope entries produced by this query,
                 * so we do not really add them to the scope region (hence the code is commented out). 
                 *

                //
                // All the scopes of this current scope region have been rolled back. 
                // Add new scope with all the projected items on it.
                // 
                sr.EnterScope(); 
                if (selectClause.SelectKind == AST.SelectKind.SelectRow)
                { 
                    foreach (var projectionExpression in projectionItems)
                    {
                        DbVariableReferenceExpression projectionExpressionRef = projectionExpression.Value.ResultType.Variable(projectionExpression.Key);
                        sr.CurrentScope.Add(projectionExpressionRef.VariableName, 
                            new SourceScopeEntry(projectionExpressionRef).AddParentVar(sortBinding.Variable));
                    } 
                } 
                else
                { 
                    Debug.Assert(selectClause.SelectKind == AST.SelectKind.SelectValue, "selectClause.SelectKind == AST.SelectKind.SelectValue");
                    Debug.Assert(projectionItems.Count == 1, "projectionItems.Count == 1");

                    sr.CurrentScope.Add(projectionItems[0].Key, new SourceScopeEntry(sortBinding.Variable)); 
                }*/
            } 
            else 
            {
                sr.CurrentScopeRegion.ApplyToScopeEntries(scopeEntry => 
                {
                    Debug.Assert(scopeEntry.EntryKind == ScopeEntryKind.SourceVar || scopeEntry.EntryKind == ScopeEntryKind.InvalidGroupInputRef,
                        "scopeEntry.EntryKind == ScopeEntryKind.SourceVar || scopeEntry.EntryKind == ScopeEntryKind.InvalidGroupInputRef");
 
                    if (scopeEntry.EntryKind == ScopeEntryKind.SourceVar)
                    { 
                        ((SourceScopeEntry)scopeEntry).ReplaceParentVar(sortBinding.Variable); 
                    }
                }); 
            }

            Debug.Assert(null != sortBinding, "null != sortBinding");
 
            return sortBinding;
        } 
 
        /// 
        /// [....]: Temporary workaround for 2/3 milestone. 
        /// Convert "x in multiset(y1, y2, ..., yn)" into
        /// x = y1 or x = y2 or x = y3 ...
        /// 
        /// semantic resolver 
        /// left-expression (the probe)
        /// right expression (the collection) 
        /// Or chain of equality comparisons 
        private static DbExpression ConvertSimpleInExpression(SemanticResolver sr, DbExpression left, DbExpression right)
        { 
            // Only handle cases when the right-side is a new instance expression
            Debug.Assert(right.ExpressionKind == DbExpressionKind.NewInstance, "right.ExpressionKind == DbExpressionKind.NewInstance");
            DbNewInstanceExpression rightColl = (DbNewInstanceExpression)right;
 
            if (rightColl.Arguments.Count == 0)
            { 
                return DbExpressionBuilder.False; 
            }
 
            var predicates = rightColl.Arguments.Select(arg => left.Equal(arg));
            List args = new List(predicates);
            DbExpression orExpr = Utils.Helpers.BuildBalancedTreeInPlace(args,
                (prev, next) => prev.Or(next) 
            );
 
            return orExpr; 
        }
 
        private static bool IsStringType(TypeUsage type)
        {
            return TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String);
        } 

        private static bool IsBooleanType(TypeUsage type) 
        { 
            return TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.Boolean);
        } 

        private static bool IsSubOrSuperType(TypeUsage type1, TypeUsage type2)
        {
            return TypeSemantics.IsStructurallyEqual(type1, type2) || type1.IsSubtypeOf(type2) || type2.IsSubtypeOf(type1); 
        }
 
        private static bool IsUntypedNullExpression(DbExpression expression) 
        {
            return expression.ExpressionKind == DbExpressionKind.Null && TypeSemantics.IsNullType(expression.ResultType); 
        }

        #region Expression converters
 
        private delegate ExpressionResolution AstExprConverter(AST.Node astExpr, SemanticResolver sr);
        private static readonly Dictionary _astExprConverters = CreateAstExprConverters(); 
        private delegate DbExpression BuiltInExprConverter(AST.BuiltInExpr astBltInExpr, SemanticResolver sr); 
        private static readonly Dictionary _builtInExprConverter = CreateBuiltInExprConverter();
 
        private static Dictionary CreateAstExprConverters()
        {
            const int NumberOfElements = 17;  // number of elements initialized by the dictionary
            Dictionary astExprConverters = new Dictionary(NumberOfElements); 
            astExprConverters.Add(typeof(AST.Literal), new AstExprConverter(ConvertLiteral));
            astExprConverters.Add(typeof(AST.QueryParameter), new AstExprConverter(ConvertParameter)); 
            astExprConverters.Add(typeof(AST.Identifier), new AstExprConverter(ConvertIdentifier)); 
            astExprConverters.Add(typeof(AST.DotExpr), new AstExprConverter(ConvertDotExpr));
            astExprConverters.Add(typeof(AST.BuiltInExpr), new AstExprConverter(ConvertBuiltIn)); 
            astExprConverters.Add(typeof(AST.QueryExpr), new AstExprConverter(ConvertQuery));
            astExprConverters.Add(typeof(AST.ParenExpr), new AstExprConverter(ConvertParenExpr));
            astExprConverters.Add(typeof(AST.RowConstructorExpr), new AstExprConverter(ConvertRowConstructor));
            astExprConverters.Add(typeof(AST.MultisetConstructorExpr), new AstExprConverter(ConvertMultisetConstructor)); 
            astExprConverters.Add(typeof(AST.CaseExpr), new AstExprConverter(ConvertCaseExpr));
            astExprConverters.Add(typeof(AST.RelshipNavigationExpr), new AstExprConverter(ConvertRelshipNavigationExpr)); 
            astExprConverters.Add(typeof(AST.RefExpr), new AstExprConverter(ConvertRefExpr)); 
            astExprConverters.Add(typeof(AST.DerefExpr), new AstExprConverter(ConvertDeRefExpr));
            astExprConverters.Add(typeof(AST.MethodExpr), new AstExprConverter(ConvertMethodExpr)); 
            astExprConverters.Add(typeof(AST.CreateRefExpr), new AstExprConverter(ConvertCreateRefExpr));
            astExprConverters.Add(typeof(AST.KeyExpr), new AstExprConverter(ConvertKeyExpr));
            astExprConverters.Add(typeof(AST.GroupPartitionExpr), new AstExprConverter(ConvertGroupPartitionExpr));
            Debug.Assert(NumberOfElements == astExprConverters.Count, "The number of elements and initial capacity don't match"); 
            return astExprConverters;
        } 
 
        private static Dictionary CreateBuiltInExprConverter()
        { 
            Dictionary builtInExprConverter = new Dictionary(sizeof(AST.BuiltInKind));

            ////////////////////////////
            // Arithmetic Expressions 
            ////////////////////////////
 
            // 
            // e1 + e2
            // 
            #region e1 + e2
            builtInExprConverter.Add(AST.BuiltInKind.Plus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                Pair args = ConvertPlusOperands(bltInExpr, sr); 

                if (TypeSemantics.IsNumericType(args.Left.ResultType)) 
                { 
                    return args.Left.Plus(args.Right);
                } 
                else
                {
                    //
                    // fold '+' operator into concat canonical function 
                    //
                    MetadataFunctionGroup function; 
                    if (!sr.TypeResolver.TryGetFunctionFromMetadata("Edm.Concat", out function)) 
                    {
                        throw EntityUtil.EntitySqlError(bltInExpr.ErrCtx, Strings.ConcatBuiltinNotSupported); 
                    }

                    List argTypes = new List(2);
                    argTypes.Add(args.Left.ResultType); 
                    argTypes.Add(args.Right.ResultType);
 
                    bool isAmbiguous = false; 
                    EdmFunction concatFunction = FunctionOverloadResolver.ResolveFunctionOverloads(
                        function.FunctionMetadata, 
                        argTypes,
                        false /* isGroupAggregate */,
                        out isAmbiguous);
 
                    if (null == concatFunction || isAmbiguous)
                    { 
                        throw EntityUtil.EntitySqlError(bltInExpr.ErrCtx, Strings.ConcatBuiltinNotSupported); 
                    }
 
                    return concatFunction.Invoke(new[] { args.Left, args.Right });
                }

            }); 
            #endregion
 
            // 
            // e1 - e2
            // 
            #region e1 - e2
            builtInExprConverter.Add(AST.BuiltInKind.Minus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                Pair args = ConvertArithmeticArgs(bltInExpr, sr); 

                return args.Left.Minus(args.Right); 
            }); 
            #endregion
 
            //
            // e1 * e2
            //
            #region e1 * e2 
            builtInExprConverter.Add(AST.BuiltInKind.Multiply, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertArithmeticArgs(bltInExpr, sr); 

                return args.Left.Multiply(args.Right); 
            });
            #endregion

            // 
            // e1 / e2
            // 
            #region e1 / e2 
            builtInExprConverter.Add(AST.BuiltInKind.Divide, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertArithmeticArgs(bltInExpr, sr);

                return args.Left.Divide(args.Right);
            }); 
            #endregion
 
            // 
            // e1 % e2
            // 
            #region e1 % e2
            builtInExprConverter.Add(AST.BuiltInKind.Modulus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                Pair args = ConvertArithmeticArgs(bltInExpr, sr); 

                return args.Left.Modulo(args.Right); 
            }); 
            #endregion
 
            //
            // - e
            //
            #region - e 
            builtInExprConverter.Add(AST.BuiltInKind.UnaryMinus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                DbExpression argument = ConvertArithmeticArgs(bltInExpr, sr).Left; 
                if (TypeSemantics.IsUnsignedNumericType(argument.ResultType))
                { 
                    TypeUsage closestPromotableType = null;
                    if (!TypeHelpers.TryGetClosestPromotableType(argument.ResultType, out closestPromotableType))
                    {
                        throw EntityUtil.EntitySqlError(Strings.InvalidUnsignedTypeForUnaryMinusOperation(argument.ResultType.EdmType.FullName)); 
                    }
                } 
 
                DbExpression unaryExpr = argument.UnaryMinus();
                return unaryExpr; 
            });
            #endregion

            // 
            // + e
            // 
            #region + e 
            builtInExprConverter.Add(AST.BuiltInKind.UnaryPlus, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                return ConvertArithmeticArgs(bltInExpr, sr).Left;
            });
            #endregion
 
            ////////////////////////////
            // Logical Expressions 
            //////////////////////////// 

            // 
            // e1 AND e2
            // e1 && e2
            //
            #region e1 AND e2 
            builtInExprConverter.Add(AST.BuiltInKind.And, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = SemanticAnalyzer.ConvertLogicalArgs(bltInExpr, sr); 

                return args.Left.And(args.Right); 
            });
            #endregion

            // 
            // e1 OR e2
            // e1 || e2 
            // 
            #region e1 OR e2
            builtInExprConverter.Add(AST.BuiltInKind.Or, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                Pair args = SemanticAnalyzer.ConvertLogicalArgs(bltInExpr, sr);

                return args.Left.Or(args.Right); 
            });
            #endregion 
 
            //
            // NOT e 
            // ! e
            //
            #region NOT e
            builtInExprConverter.Add(AST.BuiltInKind.Not, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                return ConvertLogicalArgs(bltInExpr, sr).Left.Not(); 
            }); 
            #endregion
 
            ////////////////////////////
            // Comparison Expressions
            ////////////////////////////
 
            //
            // e1 == e2 | e1 = e2 
            // 
            #region e1 == e2
            builtInExprConverter.Add(AST.BuiltInKind.Equal, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                Pair args = ConvertEqualCompArgs(bltInExpr, sr);

                return args.Left.Equal(args.Right); 
            });
            #endregion 
 
            //
            // e1 != e2 | e1 <> e2 
            //
            #region e1 != e2
            builtInExprConverter.Add(AST.BuiltInKind.NotEqual, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertEqualCompArgs(bltInExpr, sr);
 
                // 

                return args.Left.Equal(args.Right).Not(); 
            });
            #endregion

            // 
            // e1 >= e2
            // 
            #region e1 >= e2 
            builtInExprConverter.Add(AST.BuiltInKind.GreaterEqual, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertOrderCompArgs(bltInExpr, sr);

                return args.Left.GreaterThanOrEqual(args.Right);
            }); 
            #endregion
 
            // 
            // e1 > e2
            // 
            #region e1 > e2
            builtInExprConverter.Add(AST.BuiltInKind.GreaterThan, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                Pair args = ConvertOrderCompArgs(bltInExpr, sr); 

                return args.Left.GreaterThan(args.Right); 
            }); 
            #endregion
 
            //
            // e1 <= e2
            //
            #region e1 <= e2 
            builtInExprConverter.Add(AST.BuiltInKind.LessEqual, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertOrderCompArgs(bltInExpr, sr); 

                return args.Left.LessThanOrEqual(args.Right); 
            });
            #endregion

            // 
            // e1 < e2
            // 
            #region e1 < e2 
            builtInExprConverter.Add(AST.BuiltInKind.LessThan, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertOrderCompArgs(bltInExpr, sr);

                return args.Left.LessThan(args.Right);
            }); 
            #endregion
 
 
            ////////////////////////////
            //    SET EXPRESSIONS 
            ////////////////////////////


            // 
            // e1 UNION e2
            // 
            #region e1 UNION e2 
            builtInExprConverter.Add(AST.BuiltInKind.Union, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertSetArgs(bltInExpr, sr);

                return args.Left.UnionAll(args.Right).Distinct();
            }); 
            #endregion
 
            // 
            // e1 UNION ALL e2
            // 
            #region e1 UNION ALL e2
            builtInExprConverter.Add(AST.BuiltInKind.UnionAll, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                Pair args = ConvertSetArgs(bltInExpr, sr); 

                return args.Left.UnionAll(args.Right); 
            }); 
            #endregion
 
            //
            // e1 INTERSECT e2
            //
            #region e1 INTERSECT e2 
            builtInExprConverter.Add(AST.BuiltInKind.Intersect, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertSetArgs(bltInExpr, sr); 

                return args.Left.Intersect(args.Right); 
            });
            #endregion

            // 
            // e1 OVERLAPS e2
            // 
            #region e1 OVERLAPS e1 
            builtInExprConverter.Add(AST.BuiltInKind.Overlaps, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertSetArgs(bltInExpr, sr);

                return args.Left.Intersect(args.Right).IsEmpty().Not();
            }); 
            #endregion
 
            // 
            // ANYELEMENT( e )
            // 
            #region ANYELEMENT( e )
            builtInExprConverter.Add(AST.BuiltInKind.AnyElement, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                return ConvertSetArgs(bltInExpr, sr).Left.Element(); 
            });
            #endregion 
 
            //
            // ELEMENT( e ) 
            //
            #region ELEMENT( e ) - NOT SUPPORTED IN ORCAS TIMEFRAME
            builtInExprConverter.Add(AST.BuiltInKind.Element, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                throw EntityUtil.NotSupported(Strings.ElementOperatorIsNotSupported);
            }); 
            #endregion 

            // 
            // e1 EXCEPT e2
            //
            #region e1 EXCEPT e2
            builtInExprConverter.Add(AST.BuiltInKind.Except, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                Pair args = ConvertSetArgs(bltInExpr, sr); 
 
                return args.Left.Except(args.Right);
            }); 
            #endregion

            //
            // EXISTS( e ) 
            //
            #region EXISTS( e ) 
            builtInExprConverter.Add(AST.BuiltInKind.Exists, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                return ConvertSetArgs(bltInExpr, sr).Left.IsEmpty().Not(); 
            });
            #endregion

            // 
            // FLATTEN( e )
            // 
            #region FLATTEN( e ) 
            builtInExprConverter.Add(AST.BuiltInKind.Flatten, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                DbExpression elemExpr = ConvertValueExpression(bltInExpr.Arg1, sr);

                if (!TypeSemantics.IsCollectionType(elemExpr.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidFlattenArgument);
                } 
 
                if (!TypeSemantics.IsCollectionType(TypeHelpers.GetElementTypeUsage(elemExpr.ResultType)))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidFlattenArgument);
                }

                DbExpressionBinding leftExpr = elemExpr.BindAs(sr.GenerateInternalName("l_flatten")); 

                DbExpressionBinding rightExpr = leftExpr.Variable.BindAs(sr.GenerateInternalName("r_flatten")); 
 
                DbExpressionBinding applyBinding = leftExpr.CrossApply(rightExpr).BindAs(sr.GenerateInternalName("flatten"));
 
                return applyBinding.Project(applyBinding.Variable.Property(rightExpr.VariableName));
            });
            #endregion
 
            //
            // e1 IN e2 
            // 
            #region e1 IN e2
            builtInExprConverter.Add(AST.BuiltInKind.In, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                Pair args = ConvertInExprArgs(bltInExpr, sr);

                // [....]: Temporary workaround for 2/3 milestone. 
                // Convert "x in multiset(y1, y2, ..., yn)" into
                //    x = y1 or x = y2 or x = y3 ... 
                // 
                if (args.Right.ExpressionKind == DbExpressionKind.NewInstance)
                { 
                    return ConvertSimpleInExpression(sr, args.Left, args.Right);
                }
                else
                { 
                    DbExpressionBinding rSet = args.Right.BindAs(sr.GenerateInternalName("in-filter"));
 
                    DbExpression leftIn = args.Left; 
                    DbExpression rightSet = rSet.Variable;
 
                    DbExpression exists = rSet.Filter(leftIn.Equal(rightSet)).IsEmpty().Not();

                    List whenExpr = new List(1);
                    whenExpr.Add(leftIn.IsNull()); 
                    List thenExpr = new List(1);
                    thenExpr.Add(DbExpressionBuilder.Null(sr.TypeResolver.BooleanType)); 
 
                    DbExpression left = DbExpressionBuilder.Case(whenExpr, thenExpr, DbExpressionBuilder.False);
 
                    DbExpression converted = left.Or(exists);

                    return converted;
                } 
            });
            #endregion 
 
            //
            // e1 NOT IN e1 
            //
            #region e1 NOT IN e1
            builtInExprConverter.Add(AST.BuiltInKind.NotIn, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertInExprArgs(bltInExpr, sr);
 
                if (args.Right.ExpressionKind == DbExpressionKind.NewInstance) 
                {
                    return ConvertSimpleInExpression(sr, args.Left, args.Right).Not(); 
                }
                else
                {
                    DbExpressionBinding rSet = args.Right.BindAs(sr.GenerateInternalName("in-filter")); 

                    DbExpression leftIn = args.Left; 
                    DbExpression rightSet = rSet.Variable; 

                    DbExpression exists = rSet.Filter(leftIn.Equal(rightSet)).IsEmpty(); 

                    List whenExpr = new List(1);
                    whenExpr.Add(leftIn.IsNull());
                    List thenExpr = new List(1); 
                    thenExpr.Add(DbExpressionBuilder.Null(sr.TypeResolver.BooleanType));
 
                    DbExpression left = DbExpressionBuilder.Case(whenExpr, thenExpr, DbExpressionBuilder.True); 

                    DbExpression converted = left.And(exists); 

                    return converted;
                }
            }); 
            #endregion
 
            // 
            // SET( e ) - DISTINCT( e ) before
            // 
            #region SET( e )
            builtInExprConverter.Add(AST.BuiltInKind.Distinct, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                Pair args = ConvertSetArgs(bltInExpr, sr); 

                return args.Left.Distinct(); 
            }); 
            #endregion
 

            ////////////////////////////
            // Nullabity Expressions
            //////////////////////////// 

            // 
            // e IS NULL 
            //
            #region e IS NULL 
            builtInExprConverter.Add(AST.BuiltInKind.IsNull, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            {
                DbExpression isNullExpr = ConvertValueExpression(bltInExpr.Arg1, sr);
 
                //
                // ensure expression type is valid for this operation 
                // 
                if (!TypeHelpers.IsValidIsNullOpType(isNullExpr.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.IsNullInvalidType);
                }

                return IsUntypedNullExpression(isNullExpr) ? DbExpressionBuilder.True : (DbExpression)isNullExpr.IsNull(); 
            });
            #endregion 
 
            //
            // e IS NOT NULL 
            //
            #region e IS NOT NULL
            builtInExprConverter.Add(AST.BuiltInKind.IsNotNull, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                DbExpression isNullExpr = ConvertValueExpression(bltInExpr.Arg1, sr);
 
                // 
                // ensure expression type is valid for this operation
                // 
                if (!TypeHelpers.IsValidIsNullOpType(isNullExpr.ResultType))
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.IsNullInvalidType);
                } 

                isNullExpr = IsUntypedNullExpression(isNullExpr) ? DbExpressionBuilder.True : (DbExpression)isNullExpr.IsNull(); 
 
                return isNullExpr.Not();
            }); 
            #endregion


            //////////////////////////// 
            //    Type Expressions
            //////////////////////////// 
 
            //
            // e IS OF ( [ONLY] T ) 
            //
            #region e IS OF ( [ONLY] T )
            builtInExprConverter.Add(AST.BuiltInKind.IsOf, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertTypeExprArgs(bltInExpr, sr);
 
                bool isOnly = (bool)((AST.Literal)bltInExpr.Arg3).Value; 
                bool isNot = (bool)((AST.Literal)bltInExpr.Arg4).Value;
                bool isNominalTypeAllowed = sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode; 

                if (TypeSemantics.IsNullType(args.Left.ResultType))
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.ExpressionCannotBeNull); 
                }
 
                if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(args.Left.ResultType)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, 
                        Strings.ExpressionTypeMustBeEntityType(Strings.CtxIsOf,
                                                               args.Left.ResultType.EdmType.BuiltInTypeKind.ToString(),
                                                               args.Left.ResultType.EdmType.FullName));
                } 
                else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(args.Left.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, 
                        Strings.ExpressionTypeMustBeNominalType(Strings.CtxIsOf,
                                                                args.Left.ResultType.EdmType.BuiltInTypeKind.ToString(), 
                                                                args.Left.ResultType.EdmType.FullName));
                }

                if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(args.Right)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeEntityType(Strings.CtxIsOf, 
                                                                                                        args.Right.EdmType.BuiltInTypeKind.ToString(), 
                                                                                                        args.Right.EdmType.FullName));
                } 
                else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(args.Right))
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeNominalType(Strings.CtxIsOf,
                                                                                                         args.Right.EdmType.BuiltInTypeKind.ToString(), 
                                                                                                         args.Right.EdmType.FullName));
                } 
 
                if (!TypeSemantics.IsPolymorphicType(args.Left.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.TypeMustBeInheritableType);
                }

                if (!TypeSemantics.IsPolymorphicType(args.Right)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeInheritableType); 
                } 

                if (!IsSubOrSuperType(args.Left.ResultType, args.Right)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.ErrCtx, Strings.NotASuperOrSubType(args.Left.ResultType.EdmType.FullName,
                                                                                                 args.Right.EdmType.FullName));
                } 

                args.Right = TypeHelpers.GetReadOnlyType(args.Right); 
 
                DbExpression retExpr = null;
                if (isOnly) 
                {
                    retExpr = args.Left.IsOfOnly(args.Right);
                }
                else 
                {
                    retExpr = args.Left.IsOf(args.Right); 
                } 

                if (isNot) 
                {
                    retExpr = retExpr.Not();
                }
 
                return retExpr;
            }); 
            #endregion 

            // 
            // TREAT( e as T )
            //
            #region TREAT( e as T )
            builtInExprConverter.Add(AST.BuiltInKind.Treat, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                Pair args = ConvertTypeExprArgs(bltInExpr, sr); 
 
                bool isNominalTypeAllowed = sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode;
 
                if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(args.Right))
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx,
                        Strings.TypeMustBeEntityType(Strings.CtxTreat, 
                                                     args.Right.EdmType.BuiltInTypeKind.ToString(),
                                                     args.Right.EdmType.FullName)); 
                } 
                else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(args.Right))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx,
                        Strings.TypeMustBeNominalType(Strings.CtxTreat,
                                                      args.Right.EdmType.BuiltInTypeKind.ToString(),
                                                      args.Right.EdmType.FullName)); 
                }
 
                if (TypeSemantics.IsNullType(args.Left.ResultType)) 
                {
                    args.Left = DbExpressionBuilder.Null(args.Right); 
                }
                else if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(args.Left.ResultType))
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, 
                        Strings.ExpressionTypeMustBeEntityType(Strings.CtxTreat,
                                                               args.Left.ResultType.EdmType.BuiltInTypeKind.ToString(), 
                                                               args.Left.ResultType.EdmType.FullName)); 
                }
                else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(args.Left.ResultType)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
                        Strings.ExpressionTypeMustBeNominalType(Strings.CtxTreat,
                                                                args.Left.ResultType.EdmType.BuiltInTypeKind.ToString(), 
                                                                args.Left.ResultType.EdmType.FullName));
                } 
 
                if (!TypeSemantics.IsPolymorphicType(args.Left.ResultType))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.TypeMustBeInheritableType);
                }

                if (!TypeSemantics.IsPolymorphicType(args.Right)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.TypeMustBeInheritableType); 
                } 

                if (!IsSubOrSuperType(args.Left.ResultType, args.Right)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.NotASuperOrSubType(args.Left.ResultType.EdmType.FullName,
                                                                                                      args.Right.EdmType.FullName));
                } 

                return args.Left.TreatAs(TypeHelpers.GetReadOnlyType(args.Right)); 
            }); 
            #endregion
 
            //
            // CAST( e AS T )
            //
            #region CAST( e AS T ) 
            builtInExprConverter.Add(AST.BuiltInKind.Cast, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                Pair args = ConvertTypeExprArgs(bltInExpr, sr); 

                // 
                // ensure CAST target type is Scalar
                //
                if (!TypeSemantics.IsPrimitiveType(args.Right))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.InvalidCastType);
                } 
 
                if (IsUntypedNullExpression(args.Left))
                { 
                    return DbExpressionBuilder.Null(args.Right).CastTo(args.Right);
                }

                if (args.Left.ResultType.BuiltInTypeKind != BuiltInTypeKind.EnumType) 
                {
                    if (!TypeSemantics.IsPrimitiveType(args.Left.ResultType)) 
                    { 
                        throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidCastExpressionType);
                    } 

                    if (!TypeSemantics.IsCastAllowed(args.Left.ResultType, args.Right))
                    {
                        throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.InvalidCast(args.Left.ResultType.EdmType, args.Right.EdmType.FullName)); 
                    }
                } 
 
                return args.Left.CastTo(TypeHelpers.GetReadOnlyType(args.Right));
            }); 
            #endregion

            //
            // OFTYPE( [ONLY] e, T ) 
            //
            #region OFTYPE( [ONLY] e, T ) 
            builtInExprConverter.Add(AST.BuiltInKind.OfType, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            {
                Pair args = ConvertTypeExprArgs(bltInExpr, sr); 

                bool isOnly = (bool)((AST.Literal)bltInExpr.Arg3).Value;

                bool isNominalTypeAllowed = sr.ParserOptions.ParserCompilationMode == ParserOptions.CompilationMode.RestrictedViewGenerationMode; 

                if (!TypeSemantics.IsCollectionType(args.Left.ResultType)) 
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.ExpressionMustBeCollection);
                } 

                TypeUsage elementType = TypeHelpers.GetElementTypeUsage(args.Left.ResultType);
                if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(elementType))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
                        Strings.OfTypeExpressionElementTypeMustBeEntityType(elementType.EdmType.BuiltInTypeKind.ToString(), elementType)); 
                } 
                else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(elementType))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx,
                        Strings.OfTypeExpressionElementTypeMustBeNominalType(elementType.EdmType.BuiltInTypeKind.ToString(), elementType));
                }
 
                if (!isNominalTypeAllowed && !TypeSemantics.IsEntityType(args.Right))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, 
                        Strings.TypeMustBeEntityType(Strings.CtxOfType, args.Right.EdmType.BuiltInTypeKind.ToString(), args.Right.EdmType.FullName));
                } 
                else if (isNominalTypeAllowed && !TypeSemantics.IsNominalType(args.Right))
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx,
                        Strings.TypeMustBeNominalType(Strings.CtxOfType, args.Right.EdmType.BuiltInTypeKind.ToString(), args.Right.EdmType.FullName)); 
                }
 
                if (isOnly && args.Right.EdmType.Abstract) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.OfTypeOnlyTypeArgumentCannotBeAbstract(args.Right.EdmType.FullName)); 
                }

                if (!IsSubOrSuperType(elementType, args.Right))
                { 
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.NotASuperOrSubType(elementType.EdmType.FullName, args.Right.EdmType.FullName));
                } 
 
                DbExpression ofTypeExpression = null;
                if (isOnly) 
                {
                    ofTypeExpression = args.Left.OfTypeOnly(TypeHelpers.GetReadOnlyType(args.Right));
                }
                else 
                {
                    ofTypeExpression = args.Left.OfType(TypeHelpers.GetReadOnlyType(args.Right)); 
                } 

                return ofTypeExpression; 
            });
            #endregion

            // 
            // e LIKE pattern [ESCAPE escape]
            // 
            #region e LIKE pattern [ESCAPE escape] 
            builtInExprConverter.Add(AST.BuiltInKind.Like, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr)
            { 
                DbExpression likeExpr = null;

                DbExpression matchExpr = ConvertValueExpression(bltInExpr.Arg1, sr);
 
                if (TypeSemantics.IsNullType(matchExpr.ResultType))
                { 
                    matchExpr = DbExpressionBuilder.Null(sr.TypeResolver.StringType); 
                }
                else if (!IsStringType(matchExpr.ResultType)) 
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.LikeArgMustBeStringType);
                }
 
                DbExpression patternExpr = ConvertValueExpression(bltInExpr.Arg2, sr);
 
                if (patternExpr is UntypedNullExpression) 
                {
                    patternExpr = DbExpressionBuilder.Null(sr.TypeResolver.StringType); 
                }
                else if (!IsStringType(patternExpr.ResultType))
                {
                    throw EntityUtil.EntitySqlError(bltInExpr.Arg2.ErrCtx, Strings.LikeArgMustBeStringType); 
                }
 
                if (3 == bltInExpr.ArgCount) 
                {
                    DbExpression escapeExpr = ConvertValueExpression(bltInExpr.Arg3, sr); 

                    if (escapeExpr is UntypedNullExpression)
                    {
                        escapeExpr = DbExpressionBuilder.Null(sr.TypeResolver.StringType); 
                    }
                    else if (!IsStringType(escapeExpr.ResultType)) 
                    { 
                        throw EntityUtil.EntitySqlError(bltInExpr.Arg3.ErrCtx, Strings.LikeArgMustBeStringType);
                    } 

                    likeExpr = matchExpr.Like(patternExpr, escapeExpr);
                }
                else 
                {
                    likeExpr = matchExpr.Like(patternExpr); 
                } 

                return likeExpr; 
            });
            #endregion

            // 
            // e BETWEEN e1 AND e2
            // 
            #region e BETWEEN e1 AND e2 
            builtInExprConverter.Add(AST.BuiltInKind.Between, ConvertBetweenExpr);
            #endregion 

            //
            // e NOT BETWEEN e1 AND e2
            // 
            #region e NOT BETWEEN e1 AND e2
            builtInExprConverter.Add(AST.BuiltInKind.NotBetween, delegate(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
            { 
                return ConvertBetweenExpr(bltInExpr, sr).Not();
            }); 
            #endregion

            return builtInExprConverter;
        } 

        private static DbExpression ConvertBetweenExpr(AST.BuiltInExpr bltInExpr, SemanticResolver sr) 
        { 
            Debug.Assert(bltInExpr.Kind == AST.BuiltInKind.Between || bltInExpr.Kind == AST.BuiltInKind.NotBetween, "bltInExpr.Kind must be Between or NotBetween");
            Debug.Assert(bltInExpr.ArgCount == 3, "bltInExpr.ArgCount == 3"); 

            //
            // convert lower and upper limits
            // 
            Pair limitsExpr = ConvertUntypedNulls(
                ConvertValueExpression(bltInExpr.Arg2, sr), 
                ConvertValueExpression(bltInExpr.Arg3, sr), 
                bltInExpr.Arg1.ErrCtx,
                () => Strings.BetweenLimitsCannotBeUntypedNulls); 

            //
            // Get and check common type for limits
            // 
            TypeUsage rangeCommonType = TypeHelpers.GetCommonTypeUsage(limitsExpr.Left.ResultType, limitsExpr.Right.ResultType);
            if (null == rangeCommonType) 
            { 
                throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.BetweenLimitsTypesAreNotCompatible(limitsExpr.Left.ResultType.EdmType.FullName, limitsExpr.Right.ResultType.EdmType.FullName));
            } 

            //
            // check if limit types are order-comp
            // 
            if (!TypeSemantics.IsOrderComparableTo(limitsExpr.Left.ResultType, limitsExpr.Right.ResultType))
            { 
                throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.BetweenLimitsTypesAreNotOrderComparable(limitsExpr.Left.ResultType.EdmType.FullName, limitsExpr.Right.ResultType.EdmType.FullName)); 
            }
 
            //
            // convert value expression
            //
            DbExpression valueExpr = ConvertValueExpression(bltInExpr.Arg1, sr); 

            // 
            // Fixup value type if untyped 
            //
            if (TypeSemantics.IsNullType(valueExpr.ResultType)) 
            {
                valueExpr = DbExpressionBuilder.Null(rangeCommonType);
            }
 
            //
            // check if valueExpr is order-comparable to limits 
            // 
            if (!TypeSemantics.IsOrderComparableTo(valueExpr.ResultType, rangeCommonType))
            { 
                throw EntityUtil.EntitySqlError(bltInExpr.Arg1.ErrCtx, Strings.BetweenValueIsNotOrderComparable(valueExpr.ResultType.EdmType.FullName, rangeCommonType.EdmType.FullName));
            }

            return valueExpr.GreaterThanOrEqual(limitsExpr.Left).And(valueExpr.LessThanOrEqual(limitsExpr.Right)); 
        }
        #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