SqlNode.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DLinq / Dlinq / SqlClient / Common / SqlNode.cs / 1 / SqlNode.cs

                            using System; 
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq.Expressions; 
using System.Diagnostics;
using System.Data; 
 
namespace System.Data.Linq.SqlClient {
    using System.Data.Linq.Mapping; 
    using System.Data.Linq.Provider;
    using System.Diagnostics.CodeAnalysis;

    internal enum SqlNodeType { 
        Add,
        Alias, 
        AliasRef, 
        And,
        Assign, 
        Avg,
        Between,
        BitAnd,
        BitNot, 
        BitOr,
        BitXor, 
        Block, 
        Cast,
        ClientArray, 
        ClientCase,
        ClientParameter,
        ClientQuery,
        ClrLength, 
        Coalesce,
        Column, 
        ColumnRef, 
        Concat,
        Convert, 
        Count,
        Covar,
        Delete,
        DiscriminatedType, 
        DiscriminatorOf,
        Div, 
        DoNotVisit, 
        Element,
        ExprSet, 
        EQ,
        EQ2V,
        Exists,
        FunctionCall, 
        In,
        IncludeScope, 
        IsNotNull, 
        IsNull,
        LE, 
        Lift,
        Link,
        Like,
        LongCount, 
        LT,
        GE, 
        Grouping, 
        GT,
        Insert, 
        Join,
        JoinedCollection,
        Max,
        MethodCall, 
        Member,
        MemberAssign, 
        Min, 
        Mod,
        Mul, 
        Multiset,
        NE,
        NE2V,
        Negate, 
        New,
        Not, 
        Not2V, 
        Nop,
        ObjectType, 
        Or,
        OptionalValue,
        OuterJoinedValue,
        Parameter, 
        Property,
        Row, 
        RowNumber, 
        ScalarSubSelect,
        SearchedCase, 
        Select,
        SharedExpression,
        SharedExpressionRef,
        SimpleCase, 
        SimpleExpression,
        Stddev, 
        StoredProcedureCall, 
        Sub,
        Sum, 
        Table,
        TableValuedFunctionCall,
        Treat,
        TypeCase, 
        Union,
        Update, 
        UserColumn, 
        UserQuery,
        UserRow, 
        Variable,
        Value,
        ValueOf
    } 

    [System.Diagnostics.DebuggerDisplay("text = {Text}, \r\nsource = {SourceExpression}")] 
    internal abstract class SqlNode { 
        private SqlNodeType nodeType;
        private Expression sourceExpression; 

        internal SqlNode(SqlNodeType nodeType, Expression sourceExpression) {
            this.nodeType = nodeType;
            this.sourceExpression = sourceExpression; 
        }
 
        internal Expression SourceExpression { 
            get { return this.sourceExpression; }
        } 

        internal void ClearSourceExpression() {
            this.sourceExpression = null;
        } 

        internal SqlNodeType NodeType { 
            get { return this.nodeType; } 
        }
 
#if DEBUG
        private static DbFormatter formatter;
        internal static DbFormatter Formatter {
            get { return formatter; } 
            set { formatter = value; }
        } 
 
        internal string Text {
            get { 
                if (Formatter == null)
                    return "SqlNode.Formatter is not assigned";
                return SqlNode.Formatter.Format(this, true);
            } 
        }
#endif 
    } 

    internal abstract class SqlExpression : SqlNode { 
        private Type clrType;
        internal SqlExpression(SqlNodeType nodeType, Type clrType, Expression sourceExpression)
            : base(nodeType, sourceExpression) {
            this.clrType = clrType; 
        }
 
        internal Type ClrType { 
            get { return this.clrType; }
        } 

        // note: changing the CLR type of a node is potentially dangerous
        internal void SetClrType(Type type) {
            this.clrType = type; 
        }
 
        internal abstract ProviderType SqlType { get; } 

        ///  
        /// Drill down looking for a constant root expression, returning true if found.
        /// 
        internal bool IsConstantColumn {
            get { 
                if (this.NodeType == SqlNodeType.Column) {
                    SqlColumn col = (SqlColumn)this; 
                    if (col.Expression != null) { 
                        return col.Expression.IsConstantColumn;
                    } 
                }
                else if (this.NodeType == SqlNodeType.ColumnRef) {
                    return ((SqlColumnRef)this).Column.IsConstantColumn;
                } 
                else if (this.NodeType == SqlNodeType.OptionalValue) {
                    return ((SqlOptionalValue)this).Value.IsConstantColumn; 
                } 
                else if (this.NodeType == SqlNodeType.Value ||
                        this.NodeType == SqlNodeType.Parameter) { 
                    return true;
                }
                return false;
            } 
        }
    } 
 
    /// 
    /// A SqlExpression with a simple implementation of ClrType and SqlType. 
    /// 
    internal abstract class SqlSimpleTypeExpression : SqlExpression {
        private ProviderType sqlType;
 
        internal SqlSimpleTypeExpression(SqlNodeType nodeType, Type clrType, ProviderType sqlType, Expression sourceExpression)
            : base(nodeType, clrType, sourceExpression) { 
            this.sqlType = sqlType; 
        }
 
        internal override ProviderType SqlType {
            get { return this.sqlType; }
        }
 
        internal void SetSqlType(ProviderType type) {
            this.sqlType = type; 
        } 
    }
 
    /// 
    /// Represents the dynamic CLR type of the given object. Equivalent to obj.GetType().
    /// 
    internal class SqlObjectType : SqlExpression { 
        SqlExpression obj;
        ProviderType sqlType; 
        internal SqlObjectType(SqlExpression obj, ProviderType sqlType, Expression sourceExpression) 
            : base(SqlNodeType.ObjectType,
                   typeof(Type),  // Want this to be typeof(RuntimeType) which is the true implementation of the abstract typeof(Type) 
                   sourceExpression) {
            this.obj = obj;
            this.sqlType = sqlType;
        } 
        internal SqlExpression Object {
            set { this.obj = value; } 
            get { return this.obj; } 
        }
        internal override ProviderType SqlType { 
            get { return this.sqlType; }
        }
        internal void SetSqlType(ProviderType type) {
            this.sqlType = type; 
        }
    } 
 
    internal class SqlDiscriminatorOf : SqlSimpleTypeExpression {
        SqlExpression obj; 
        internal SqlDiscriminatorOf(SqlExpression obj, Type clrType, ProviderType sqlType, Expression sourceExpression)
            : base(SqlNodeType.DiscriminatorOf, clrType, sqlType, sourceExpression) {
            this.obj = obj;
        } 
        internal SqlExpression Object {
            get { return this.obj; } 
            set { this.obj = value; } 
        }
    } 


    /// 
    /// Represents a dynamic CLR type that is chosen based on a discriminator expression. 
    /// 
    internal class SqlDiscriminatedType : SqlExpression { 
        private ProviderType sqlType; 
        private SqlExpression discriminator;
        private MetaType targetType; 
        internal SqlDiscriminatedType(ProviderType sqlType, SqlExpression discriminator, MetaType targetType, Expression sourceExpression)
            : base(SqlNodeType.DiscriminatedType,
                   typeof(Type),
                   sourceExpression) { 
            if (discriminator == null)
                throw Error.ArgumentNull("discriminator"); 
            this.discriminator = discriminator; 
            this.targetType = targetType;
            this.sqlType = sqlType; 
        }
        internal override ProviderType SqlType {
            get { return this.sqlType; }
        } 
        internal SqlExpression Discriminator {
            get { return this.discriminator; } 
            set { this.discriminator = value; } 
        }
 
        internal MetaType TargetType {
            get { return this.targetType; }
        }
    } 

    internal abstract class SqlStatement : SqlNode { 
        internal SqlStatement(SqlNodeType nodeType, Expression sourceExpression) 
            : base(nodeType, sourceExpression) {
        } 
    }

    internal abstract class SqlSource : SqlNode {
        internal SqlSource(SqlNodeType nt, Expression sourceExpression) 
            : base(nt, sourceExpression) {
        } 
    } 

    internal class SqlSelect : SqlStatement { 
        private SqlExpression top;
        private bool isPercent;
        private bool isDistinct;
        private SqlExpression selection; 
        private SqlRow row;
        private SqlSource from; 
        private SqlExpression where; 
        private List groupBy;
        private SqlExpression having; 
        private List orderBy;
        private SqlOrderingType orderingType;
        private bool squelch;
 
        internal SqlSelect(SqlExpression selection, SqlSource from, Expression sourceExpression)
            : base(SqlNodeType.Select, sourceExpression) { 
            this.Row = new SqlRow(sourceExpression); 
            this.Selection = selection;
            this.From = from; 
            this.groupBy = new List();
            this.orderBy = new List();
            this.orderingType = SqlOrderingType.Default;
        } 

        internal SqlExpression Top { 
            get { return this.top; } 
            set { this.top = value; }
        } 

        internal bool IsPercent {
            get { return this.isPercent; }
            set { this.isPercent = value; } 
        }
 
        internal bool IsDistinct { 
            get { return this.isDistinct; }
            set { this.isDistinct = value; } 
        }

        internal SqlExpression Selection {
            get { return this.selection; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.selection = value;
            } 
        }

        internal SqlRow Row {
            get { return this.row; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.row = value;
            } 
        }

        internal SqlSource From {
            get { return this.from; } 
            set { this.from = value; }
        } 
 
        internal SqlExpression Where {
            get { return this.where; } 
            set {
                if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) {
                    throw Error.ArgumentWrongType("value", "bool", value.ClrType);
                } 
                this.where = value;
            } 
        } 

        internal List GroupBy { 
            get { return this.groupBy; }
        }

        internal SqlExpression Having { 
            get { return this.having; }
            set { 
                if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) { 
                    throw Error.ArgumentWrongType("value", "bool", value.ClrType);
                } 
                this.having = value;
            }
        }
 
        internal List OrderBy {
            get { return this.orderBy; } 
        } 

        internal SqlOrderingType OrderingType { 
            get { return this.orderingType; }
            set { this.orderingType = value; }
        }
 
        internal bool DoNotOutput {
            get { return this.squelch; } 
            set { this.squelch = value; } 
        }
    } 

    internal enum SqlOrderingType {
        Default,
        Never, 
        Blocked,
        Always 
    } 

    internal class SqlTable : SqlNode { 
        private MetaTable table;
        private MetaType rowType;
        private ProviderType sqlRowType;
        private List columns; 

        internal SqlTable(MetaTable table, MetaType rowType, ProviderType sqlRowType, Expression sourceExpression) 
            : base(SqlNodeType.Table, sourceExpression) { 
            this.table = table;
            this.rowType = rowType; 
            this.sqlRowType = sqlRowType;
            this.columns = new List();
        }
 
        internal MetaTable MetaTable {
            get { return this.table; } 
        } 

        internal string Name { 
            get { return this.table.TableName; }
        }

        internal List Columns { 
            get { return this.columns; }
        } 
 
        internal MetaType RowType {
            get { return this.rowType; } 
        }

        internal ProviderType SqlRowType {
            get { return this.sqlRowType; } 
        }
 
        internal SqlColumn Find(string columnName) { 
            foreach (SqlColumn c in this.Columns) {
                if (c.Name == columnName) 
                    return c;
            }
            return null;
        } 

    } 
 
    internal class SqlUserQuery : SqlNode {
        private string queryText; 
        private SqlExpression projection;
        private List args;
        private List columns;
 
        internal SqlUserQuery(SqlNodeType nt, SqlExpression projection, IEnumerable args, Expression source)
            : base(nt, source) { 
            this.Projection = projection; 
            this.args = (args != null) ? new List(args) : new List();
            this.columns = new List(); 
        }

        internal SqlUserQuery(string queryText, SqlExpression projection, IEnumerable args, Expression source)
            : base(SqlNodeType.UserQuery, source) { 
            this.queryText = queryText;
            this.Projection = projection; 
            this.args = (args != null) ? new List(args) : new List(); 
            this.columns = new List();
        } 

        internal string QueryText {
            get { return this.queryText; }
        } 

        internal SqlExpression Projection { 
            get { return this.projection; } 
            set {
                if (this.projection != null && this.projection.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.projection.ClrType, value.ClrType);
                this.projection = value;
            }
        } 

        internal List Arguments { 
            get { return this.args; } 
        }
 
        internal List Columns {
            get { return this.columns; }
        }
 
        internal SqlUserColumn Find(string name) {
            foreach (SqlUserColumn c in this.Columns) { 
                if (c.Name == name) 
                    return c;
            } 
            return null;
        }
    }
 
    internal class SqlStoredProcedureCall : SqlUserQuery {
        private MetaFunction function; 
 
        internal SqlStoredProcedureCall(MetaFunction function, SqlExpression projection, IEnumerable args, Expression source)
            : base(SqlNodeType.StoredProcedureCall, projection, args, source) { 
            if (function == null)
                throw Error.ArgumentNull("function");
            this.function = function;
        } 

        internal MetaFunction Function { 
            get { return this.function; } 
        }
    } 

    internal class SqlUserRow : SqlSimpleTypeExpression {
        private SqlUserQuery query;
        private MetaType rowType; 

        internal SqlUserRow(MetaType rowType, ProviderType sqlType, SqlUserQuery query, Expression source) 
            : base(SqlNodeType.UserRow, rowType.Type, sqlType, source) { 
            this.Query = query;
            this.rowType = rowType; 
        }

        internal MetaType RowType {
            get { return this.rowType; } 
        }
 
        internal SqlUserQuery Query { 
            get { return this.query; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (value.Projection != null && value.Projection.ClrType != this.ClrType)
                    throw Error.ArgumentWrongType("value", this.ClrType, value.Projection.ClrType); 
                this.query = value;
            } 
        } 
    }
 
    internal class SqlUserColumn : SqlSimpleTypeExpression {
        private SqlUserQuery query;
        private string name;
        private bool isRequired; 

        internal SqlUserColumn(Type clrType, ProviderType sqlType, SqlUserQuery query, string name, bool isRequired, Expression source) 
            : base(SqlNodeType.UserColumn, clrType, sqlType, source) { 
            this.Query = query;
            this.name = name; 
            this.isRequired = isRequired;
        }

        internal SqlUserQuery Query { 
            get { return this.query; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (this.query != null && this.query != value) 
                    throw Error.ArgumentWrongValue("value");
                this.query = value;
            }
        } 

        internal string Name { 
            get { return this.name; } 
        }
 
        internal bool IsRequired {
            get { return this.isRequired; }
        }
    } 

    internal class SqlAlias : SqlSource { 
        private string name; 
        private SqlNode node;
 
        internal SqlAlias(SqlNode node)
            : base(SqlNodeType.Alias, node.SourceExpression) {
            this.Node = node;
        } 

        internal string Name { 
            get { return this.name; } 
            set { this.name = value; }
        } 

        internal SqlNode Node {
            get { return this.node; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (!(value is SqlExpression || value is SqlSelect || value is SqlTable || value is SqlUnion)) 
                    throw Error.UnexpectedNode(value.NodeType);
                this.node = value; 
            }
        }
    }
 
    internal class SqlAliasRef : SqlExpression {
        private SqlAlias alias; 
 
        internal SqlAliasRef(SqlAlias alias)
            : base(SqlNodeType.AliasRef, GetClrType(alias.Node), alias.SourceExpression) { 
            if (alias == null)
                throw Error.ArgumentNull("alias");
            this.alias = alias;
        } 

        internal SqlAlias Alias { 
            get { return this.alias; } 
        }
 
        internal override ProviderType SqlType {
            get { return GetSqlType(this.alias.Node); }
        }
 
        private static Type GetClrType(SqlNode node) {
            SqlTableValuedFunctionCall tvf = node as SqlTableValuedFunctionCall; 
            if (tvf != null) 
                return tvf.RowType.Type;
            SqlExpression exp = node as SqlExpression; 
            if (exp != null) {
                if (TypeSystem.IsSequenceType(exp.ClrType))
                    return TypeSystem.GetElementType(exp.ClrType);
                return exp.ClrType; 
            }
            SqlSelect sel = node as SqlSelect; 
            if (sel != null) 
                return sel.Selection.ClrType;
            SqlTable tab = node as SqlTable; 
            if (tab != null)
                return tab.RowType.Type;
            SqlUnion su = node as SqlUnion;
            if (su != null) 
                return su.GetClrType();
            throw Error.UnexpectedNode(node.NodeType); 
        } 

        private static ProviderType GetSqlType(SqlNode node) { 
            SqlExpression exp = node as SqlExpression;
            if (exp != null)
                return exp.SqlType;
            SqlSelect sel = node as SqlSelect; 
            if (sel != null)
                return sel.Selection.SqlType; 
            SqlTable tab = node as SqlTable; 
            if (tab != null)
                return tab.SqlRowType; 
            SqlUnion su = node as SqlUnion;
            if (su != null)
                return su.GetSqlType();
            throw Error.UnexpectedNode(node.NodeType); 
        }
    } 
 
    internal class SqlJoin : SqlSource {
        private SqlJoinType joinType; 
        private SqlSource left;
        private SqlSource right;
        private SqlExpression condition;
 
        internal SqlJoin(SqlJoinType type, SqlSource left, SqlSource right, SqlExpression cond, Expression sourceExpression)
            : base(SqlNodeType.Join, sourceExpression) { 
            this.JoinType = type; 
            this.Left = left;
            this.Right = right; 
            this.Condition = cond;
        }

        internal SqlJoinType JoinType { 
            get { return this.joinType; }
            set { this.joinType = value; } 
        } 

        internal SqlSource Left { 
            get { return this.left; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.left = value;
            } 
        } 

        internal SqlSource Right { 
            get { return this.right; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.right = value;
            } 
        } 

        internal SqlExpression Condition { 
            get { return this.condition; }
            set { this.condition = value; }
        }
    } 

    internal enum SqlJoinType { 
        Cross, 
        Inner,
        LeftOuter, 
        CrossApply,
        OuterApply
    }
 
    internal class SqlUnion : SqlNode {
        private SqlNode left; 
        private SqlNode right; 
        private bool all;
 
        internal SqlUnion(SqlNode left, SqlNode right, bool all)
            : base(SqlNodeType.Union, right.SourceExpression) {
            this.Left = left;
            this.Right = right; 
            this.All = all;
        } 
 
        internal SqlNode Left {
            get { return this.left; } 
            set {
                Validate(value);
                this.left = value;
            } 
        }
 
        internal SqlNode Right { 
            get { return this.right; }
            set { 
                Validate(value);
                this.right = value;
            }
        } 

        internal bool All { 
            get { return this.all; } 
            set { this.all = value; }
        } 

        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
        private void Validate(SqlNode node) {
            if (node == null) 
                throw Error.ArgumentNull("node");
            if (!(node is SqlExpression || node is SqlSelect || node is SqlUnion)) 
                throw Error.UnexpectedNode(node.NodeType); 
        }
 
        internal Type GetClrType() {
            SqlExpression exp = this.Left as SqlExpression;
            if (exp != null)
                return exp.ClrType; 
            SqlSelect sel = this.Left as SqlSelect;
            if (sel != null) 
                return sel.Selection.ClrType; 
            throw Error.CouldNotGetClrType();
        } 

        internal ProviderType GetSqlType() {
            SqlExpression exp = this.Left as SqlExpression;
            if (exp != null) 
                return exp.SqlType;
            SqlSelect sel = this.Left as SqlSelect; 
            if (sel != null) 
                return sel.Selection.SqlType;
            throw Error.CouldNotGetSqlType(); 
        }
    }

    internal class SqlNop : SqlSimpleTypeExpression { 
        internal SqlNop(Type clrType, ProviderType sqlType, Expression sourceExpression)
            : base(SqlNodeType.Nop, clrType, sqlType, sourceExpression) { 
        } 
    }
 
    internal class SqlLift : SqlExpression {
        internal SqlExpression liftedExpression;

        internal SqlLift(Type type, SqlExpression liftedExpression, Expression sourceExpression) 
            : base(SqlNodeType.Lift, type, sourceExpression) {
            if (liftedExpression == null) 
                throw Error.ArgumentNull("liftedExpression"); 
            this.liftedExpression = liftedExpression;
        } 

        internal SqlExpression Expression {
            get { return this.liftedExpression; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.liftedExpression = value; 
            }
        } 

        internal override ProviderType SqlType {
            get { return this.liftedExpression.SqlType; }
        } 
    }
 
    internal enum SqlOrderType { 
        Ascending,
        Descending 
    }

    internal class SqlOrderExpression : IEquatable {
        private SqlOrderType orderType; 
        private SqlExpression expression;
 
        internal SqlOrderExpression(SqlOrderType type, SqlExpression expr) { 
            this.OrderType = type;
            this.Expression = expr; 
        }

        internal SqlOrderType OrderType {
            get { return this.orderType; } 
            set { this.orderType = value; }
        } 
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.expression != null && !this.expression.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
                this.expression = value; 
            } 
        }
 
        public override bool Equals(object obj) {
            if (this.EqualsTo(obj as SqlOrderExpression))
                return true;
 
            return base.Equals(obj);
        } 
 
        public bool Equals(SqlOrderExpression other) {
            if (this.EqualsTo(other)) 
                return true;

            return base.Equals(other);
        } 

        private bool EqualsTo(SqlOrderExpression other) { 
            if (other == null) 
                return false;
            if (object.ReferenceEquals(this, other)) 
                return true;
            if (this.OrderType != other.OrderType)
                return false;
            if (!this.Expression.SqlType.Equals(other.Expression.SqlType)) 
                return false;
 
            SqlColumn col1 = SqlOrderExpression.UnwrapColumn(this.Expression); 
            SqlColumn col2 = SqlOrderExpression.UnwrapColumn(other.Expression);
 
            if (col1 == null || col2 == null)
                return false;

            return col1 == col2; 
        }
 
        public override int GetHashCode() { 
            SqlColumn col = SqlOrderExpression.UnwrapColumn(this.Expression);
            if (col != null) 
                return col.GetHashCode();

            return base.GetHashCode();
        } 

        private static SqlColumn UnwrapColumn(SqlExpression expr) { 
            System.Diagnostics.Debug.Assert(expr != null); 

            if (expr is SqlUnary) 
                expr = ((SqlUnary)expr).Operand;
            if (expr is SqlColumn)
                return expr as SqlColumn;
            if (expr is SqlColumnRef) 
                return ((SqlColumnRef)expr).GetRootColumn();
            // 
            // For all other types return null to revert to default behavior for Equals() 
            // and GetHashCode()
            // 
            return null;
        }
    }
 
    internal class SqlRowNumber : SqlSimpleTypeExpression {
        private List orderBy; 
 
        internal List OrderBy {
            get { return orderBy; } 
        }

        internal SqlRowNumber(Type clrType, ProviderType sqlType, List orderByList, Expression sourceExpression)
            : base(SqlNodeType.RowNumber, clrType, sqlType, sourceExpression) { 
            if (orderByList == null) {
                throw Error.ArgumentNull("orderByList"); 
            } 

            this.orderBy = orderByList; 
        }
    }

    internal class SqlUnary : SqlSimpleTypeExpression { 
        private SqlExpression operand;
        private MethodInfo method; 
 
        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
        internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, Expression sourceExpression) 
            : this(nt, clrType, sqlType, expr, null, sourceExpression) {
        }

        internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, MethodInfo method, Expression sourceExpression) 
            : base(nt, clrType, sqlType, sourceExpression) {
            switch (nt) { 
                case SqlNodeType.Not: 
                case SqlNodeType.Not2V:
                case SqlNodeType.Negate: 
                case SqlNodeType.BitNot:
                case SqlNodeType.IsNull:
                case SqlNodeType.IsNotNull:
                case SqlNodeType.Count: 
                case SqlNodeType.LongCount:
                case SqlNodeType.Max: 
                case SqlNodeType.Min: 
                case SqlNodeType.Sum:
                case SqlNodeType.Avg: 
                case SqlNodeType.Stddev:
                case SqlNodeType.Covar:
                case SqlNodeType.Convert:
                case SqlNodeType.ValueOf: 
                case SqlNodeType.Cast:
                case SqlNodeType.Treat: 
                case SqlNodeType.OuterJoinedValue: 
                case SqlNodeType.ClrLength:
                    break; 
                default:
                    throw Error.UnexpectedNode(nt);
            }
            this.Operand = expr; 
            this.method = method;
        } 
 
        internal SqlExpression Operand {
            get { return this.operand; } 
            set {
                if (value == null && (this.NodeType != SqlNodeType.Count && this.NodeType != SqlNodeType.LongCount))
                    throw Error.ArgumentNull("value");
                this.operand = value; 
            }
        } 
 
        internal MethodInfo Method {
            get { return this.method; } 
        }
    }

    internal class SqlBinary : SqlSimpleTypeExpression { 
        private SqlExpression left;
        private SqlExpression right; 
        private MethodInfo method; 

        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")] 
        internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right)
            : this(nt, clrType, sqlType, left, right, null) {
        }
 
        internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method)
            : base(nt, clrType, sqlType, right.SourceExpression) { 
            switch (nt) { 
                case SqlNodeType.Add:
                case SqlNodeType.Sub: 
                case SqlNodeType.Mul:
                case SqlNodeType.Div:
                case SqlNodeType.Mod:
                case SqlNodeType.BitAnd: 
                case SqlNodeType.BitOr:
                case SqlNodeType.BitXor: 
                case SqlNodeType.And: 
                case SqlNodeType.Or:
                case SqlNodeType.GE: 
                case SqlNodeType.GT:
                case SqlNodeType.LE:
                case SqlNodeType.LT:
                case SqlNodeType.EQ: 
                case SqlNodeType.NE:
                case SqlNodeType.EQ2V: 
                case SqlNodeType.NE2V: 
                case SqlNodeType.Concat:
                case SqlNodeType.Coalesce: 
                    break;
                default:
                    throw Error.UnexpectedNode(nt);
            } 
            this.Left = left;
            this.Right = right; 
            this.method = method; 
        }
 
        internal SqlExpression Left {
            get { return this.left; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                this.left = value; 
            } 
        }
 
        internal SqlExpression Right {
            get { return this.right; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                this.right = value; 
            } 
        }
 
        internal MethodInfo Method {
            get { return this.method; }
        }
    } 

    internal class SqlBetween : SqlSimpleTypeExpression { 
        SqlExpression expression; 
        SqlExpression start;
        SqlExpression end; 

        internal SqlBetween(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression start, SqlExpression end, Expression source)
            : base(SqlNodeType.Between, clrType, sqlType, source) {
            this.expression = expr; 
            this.start = start;
            this.end = end; 
        } 

        internal SqlExpression Expression { 
            get { return this.expression; }
            set { this.expression = value; }
        }
 
        internal SqlExpression Start {
            get { return this.start; } 
            set { this.start = value; } 
        }
 
        internal SqlExpression End {
            get { return this.end; }
            set { this.end = value; }
        } 
    }
 
    internal class SqlIn : SqlSimpleTypeExpression { 
        private SqlExpression expression;
        private List values; 

        internal SqlIn(Type clrType, ProviderType sqlType, SqlExpression expression, IEnumerable values, Expression sourceExpression)
            :base(SqlNodeType.In, clrType, sqlType, sourceExpression) {
            this.expression = expression; 
            this.values = values != null ? new List(values) : new List(0);
        } 
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null) {
                    throw Error.ArgumentNull("value");
                } 
                this.expression = value;
            } 
        } 
        internal List Values {
            get { return this.values; } 
        }
    }

    internal class SqlLike : SqlSimpleTypeExpression { 
        private SqlExpression expression;
        private SqlExpression pattern; 
        private SqlExpression escape; 

        internal SqlLike(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression pattern, SqlExpression escape, Expression source) 
            : base(SqlNodeType.Like, clrType, sqlType, source) {
            if (expr == null)
                throw Error.ArgumentNull("expr");
            if (pattern == null) 
                throw Error.ArgumentNull("pattern");
            this.Expression = expr; 
            this.Pattern = pattern; 
            this.Escape = escape;
        } 

        internal SqlExpression Expression {
            get { return this.expression; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (value.ClrType != typeof(string)) 
                    throw Error.ArgumentWrongType("value", "string", value.ClrType);
                this.expression = value; 
            }
        }

        internal SqlExpression Pattern { 
            get { return this.pattern; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (value.ClrType != typeof(string)) 
                    throw Error.ArgumentWrongType("value", "string", value.ClrType);
                this.pattern = value;
            }
        } 

        internal SqlExpression Escape { 
            get { return this.escape; } 
            set {
                if (value != null && value.ClrType != typeof(string)) 
                    throw Error.ArgumentWrongType("value", "string", value.ClrType);
                this.escape = value;
            }
        } 
    }
 
    internal class SqlWhen { 
        private SqlExpression matchExpression;
        private SqlExpression valueExpression; 

        internal SqlWhen(SqlExpression match, SqlExpression value) {
            // 'match' may be null when this when represents the ELSE condition.
            if (value == null) 
                throw Error.ArgumentNull("value");
            this.Match = match; 
            this.Value = value; 
        }
 
        internal SqlExpression Match {
            get { return this.matchExpression; }
            set {
                if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
                this.matchExpression = value; 
            } 
        }
 
        internal SqlExpression Value {
            get { return this.valueExpression; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (this.valueExpression != null && !this.valueExpression.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.valueExpression.ClrType, value.ClrType); 
                this.valueExpression = value;
            } 
        }
    }

    /* 
     * Searched CASE function:
     * CASE 
     * WHEN BooleanExpression THEN resultExpression 
     * [ ...n ]
     * [ 
     * ELSE elseResultExpression
     * ]
     * END
     */ 
    internal class SqlSearchedCase : SqlExpression {
        private List whens; 
        private SqlExpression @else; 

        internal SqlSearchedCase(Type clrType, IEnumerable whens, SqlExpression @else, Expression sourceExpression) 
            : base(SqlNodeType.SearchedCase, clrType, sourceExpression) {
            if (whens == null)
                throw Error.ArgumentNull("whens");
            this.whens = new List(whens); 
            if (this.whens.Count == 0)
                throw Error.ArgumentOutOfRange("whens"); 
            this.Else = @else; 
        }
 
        internal List Whens {
            get { return this.whens; }
        }
 
        internal SqlExpression Else {
            get { return this.@else; } 
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (this.@else != null && !this.@else.ClrType.IsAssignableFrom(value.ClrType))
                    throw Error.ArgumentWrongType("value", this.@else.ClrType, value.ClrType);
                this.@else = value;
            } 
        }
 
        internal override ProviderType SqlType { 
            get { return this.whens[0].Value.SqlType; }
        } 
    }

    /*
     * Simple CASE function: 
     * CASE inputExpression
     * WHEN whenExpression THEN resultExpression 
     * [ ...n ] 
     * [
     * ELSE elseResultExpression 
     * ]
     * END
     */
    internal class SqlSimpleCase : SqlExpression { 
        private SqlExpression expression;
        private List whens = new List(); 
 
        internal SqlSimpleCase(Type clrType, SqlExpression expr, IEnumerable whens, Expression sourceExpression)
            : base(SqlNodeType.SimpleCase, clrType, sourceExpression) { 
            this.Expression = expr;
            if (whens == null)
                throw Error.ArgumentNull("whens");
            this.whens.AddRange(whens); 
            if (this.whens.Count == 0)
                throw Error.ArgumentOutOfRange("whens"); 
        } 

        internal SqlExpression Expression { 
            get { return this.expression; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (this.expression != null && this.expression.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType); 
                this.expression = value; 
            }
        } 

        internal List Whens {
            get { return this.whens; }
        } 

        internal override ProviderType SqlType { 
            get { return this.whens[0].Value.SqlType; } 
        }
    } 

    /// 
    /// A case statement that must be evaluated on the client. For example, a case statement
    /// that contains values of LINK, Element, or Multi-set are not directly handleable by 
    /// SQL.
    /// 
    /// CASE inputExpression 
    /// WHEN whenExpression THEN resultExpression
    /// [ ...n ] 
    /// END
    /// 
    internal class SqlClientCase : SqlExpression {
        private SqlExpression expression; 
        private List whens = new List();
 
        internal SqlClientCase(Type clrType, SqlExpression expr, IEnumerable whens, Expression sourceExpression) 
            : base(SqlNodeType.ClientCase, clrType, sourceExpression) {
            this.Expression = expr; 
            if (whens == null)
                throw Error.ArgumentNull("whens");
            this.whens.AddRange(whens);
            if (this.whens.Count == 0) 
                throw Error.ArgumentOutOfRange("whens");
        } 
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.expression != null && this.expression.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
                this.expression = value; 
            } 
        }
 
        internal List Whens {
            get { return this.whens; }
        }
 
        internal override ProviderType SqlType {
            get { return this.whens[0].Value.SqlType; } 
        } 
    }
 
    /// 
    /// A single WHEN clause for ClientCase.
    /// 
    internal class SqlClientWhen { 
        private SqlExpression matchExpression;
        private SqlExpression matchValue; 
 
        internal SqlClientWhen(SqlExpression match, SqlExpression value) {
            // 'match' may be null when this when represents the ELSE condition. 
            if (value == null)
                throw Error.ArgumentNull("value");
            this.Match = match;
            this.Value = value; 
        }
 
        internal SqlExpression Match { 
            get { return this.matchExpression; }
            set { 
                if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
                this.matchExpression = value;
            } 
        }
 
        internal SqlExpression Value { 
            get { return this.matchValue; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.matchValue != null && this.matchValue.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.matchValue.ClrType, value.ClrType); 
                this.matchValue = value;
            } 
        } 
    }
 
    /// 
    /// Represents the construction of an object in abstract 'super sql'.
    /// The type may be polymorphic. A discriminator field is used to determine
    /// which type in a hierarchy should be instantiated. 
    /// In the common degenerate case where the inheritance hierarchy is 1-deep
    /// the discriminator will be a constant SqlValue and there will be one 
    /// type-case-when corresponding to that type. 
    /// 
    internal class SqlTypeCase : SqlExpression { 
        private MetaType rowType;
        private SqlExpression discriminator;
        private List whens = new List();
        ProviderType sqlType; 

        internal SqlTypeCase(Type clrType, ProviderType sqlType, MetaType rowType, SqlExpression discriminator, IEnumerable whens, Expression sourceExpression) 
            : base(SqlNodeType.TypeCase, clrType, sourceExpression) { 
            this.Discriminator = discriminator;
            if (whens == null) 
                throw Error.ArgumentNull("whens");
            this.whens.AddRange(whens);
            if (this.whens.Count == 0)
                throw Error.ArgumentOutOfRange("whens"); 
            this.sqlType = sqlType;
            this.rowType = rowType; 
        } 

        internal SqlExpression Discriminator { 
            get { return this.discriminator; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (this.discriminator != null && this.discriminator.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.discriminator.ClrType, value.ClrType); 
                this.discriminator = value; 
            }
        } 

        internal List Whens {
            get { return this.whens; }
        } 

        internal override ProviderType SqlType { 
            get { return sqlType; } 
        }
 
        internal MetaType RowType {
            get { return this.rowType; }
        }
    } 

    ///  
    /// Represents one choice of object instantiation type in a type case. 
    /// When 'match' is the same as type case Discriminator then the corresponding
    /// type binding is the one used for instantiation. 
    /// 
    internal class SqlTypeCaseWhen {
        private SqlExpression match;
        private SqlExpression @new; 

        internal SqlTypeCaseWhen(SqlExpression match, SqlExpression typeBinding) { 
            this.Match = match; 
            this.TypeBinding = typeBinding;
        } 
        internal SqlExpression Match {
            get { return this.match; }
            set {
                if (this.match != null && value != null && this.match.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.match.ClrType, value.ClrType);
                this.match = value; 
            } 
        }
        internal SqlExpression TypeBinding { 
            get { return this.@new; }
            set { this.@new = value; }
        }
    } 

    internal class SqlValue : SqlSimpleTypeExpression { 
        private object value; 
        private bool isClient;
 
        internal SqlValue(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression)
            : base(SqlNodeType.Value, clrType, sqlType, sourceExpression) {
            this.value = value;
            this.isClient = isClientSpecified; 
        }
 
        internal object Value { 
            get { return this.value; }
        } 

        internal bool IsClientSpecified {
            get { return this.isClient; }
        } 
    }
 
    internal class SqlParameter : SqlSimpleTypeExpression { 
        private string name;
        private System.Data.ParameterDirection direction; 

        internal SqlParameter(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)
            : base(SqlNodeType.Parameter, clrType, sqlType, sourceExpression) {
            if (name == null) 
                throw Error.ArgumentNull("name");
            if (typeof(Type).IsAssignableFrom(clrType)) 
                throw Error.ArgumentWrongValue("clrType"); 
            this.name = name;
            this.direction = System.Data.ParameterDirection.Input; 
        }

        internal string Name {
            get { return this.name; } 
        }
 
        internal System.Data.ParameterDirection Direction { 
            get { return this.direction; }
            set { this.direction = value; } 
        }
    }

    internal class SqlVariable : SqlSimpleTypeExpression { 
        private string name;
 
        internal SqlVariable(Type clrType, ProviderType sqlType, string name, Expression sourceExpression) 
            : base(SqlNodeType.Variable, clrType, sqlType, sourceExpression) {
            if (name == null) 
                throw Error.ArgumentNull("name");
            this.name = name;
        }
 
        internal string Name {
            get { return this.name; } 
        } 
    }
 
    internal class SqlMember : SqlSimpleTypeExpression {
        private SqlExpression expression;
        private MemberInfo member;
 
        internal SqlMember(Type clrType, ProviderType sqlType, SqlExpression expr, MemberInfo member)
            : base(SqlNodeType.Member, clrType, sqlType, expr.SourceExpression) { 
            this.member = member; 
            this.Expression = expr;
        } 

        internal MemberInfo Member {
            get { return this.member; }
        } 

        internal SqlExpression Expression { 
            get { 
                return this.expression;
            } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (!this.member.ReflectedType.IsAssignableFrom(value.ClrType) && 
                    !value.ClrType.IsAssignableFrom(this.member.ReflectedType))
                    throw Error.MemberAccessIllegal(this.member, this.member.ReflectedType, value.ClrType); 
                this.expression = value; 
            }
        } 
    }

    internal class SqlColumn : SqlExpression {
        private SqlAlias alias; 
        private string name;
        private int ordinal; 
        private MetaDataMember member; 
        private SqlExpression expression;
        private ProviderType sqlType; 

        internal SqlColumn(Type clrType, ProviderType sqlType, string name, MetaDataMember member, SqlExpression expr, Expression sourceExpression)
            : base(SqlNodeType.Column, clrType, sourceExpression) {
            if (typeof(Type).IsAssignableFrom(clrType)) 
                throw Error.ArgumentWrongValue("clrType");
            this.Name = name; 
            this.member = member; 
            this.Expression = expr;
            this.Ordinal = -1; 
            if (sqlType == null)
                throw Error.ArgumentNull("sqlType");
            this.sqlType = sqlType;
            System.Diagnostics.Debug.Assert(sqlType.CanBeColumn); 
        }
 
        internal SqlColumn(string name, SqlExpression expr) 
            : this(expr.ClrType, expr.SqlType, name, null, expr, expr.SourceExpression) {
            System.Diagnostics.Debug.Assert(expr != null); 
        }

        internal SqlAlias Alias {
            get { return this.alias; } 
            set { this.alias = value; }
        } 
 
        internal string Name {
            get { return this.name; } 
            set { this.name = value; }
        }

        internal int Ordinal { 
            get { return this.ordinal; }
            set { this.ordinal = value; } 
        } 

        internal MetaDataMember MetaMember { 
            get { return this.member; }
        }

        ///  
        /// Set the column's Expression. This can change the type of the column.
        ///  
        internal SqlExpression Expression { 
            get {
                return this.expression; 
            }
            set {
                if (value != null) {
                    if (!this.ClrType.IsAssignableFrom(value.ClrType)) 
                        throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                    SqlColumnRef cref = value as SqlColumnRef; 
                    if (cref != null && cref.Column == this) 
                        throw Error.ColumnCannotReferToItself();
                } 
                this.expression = value;
            }
        }
 
        internal override ProviderType SqlType {
            get { 
                if (this.expression != null) 
                    return this.expression.SqlType;
                return this.sqlType; 
            }
        }
    }
 
    internal class SqlColumnRef : SqlExpression {
        private SqlColumn column; 
        internal SqlColumnRef(SqlColumn col) 
            : base(SqlNodeType.ColumnRef, col.ClrType, col.SourceExpression) {
            this.column = col; 
        }

        internal SqlColumn Column {
            get { return this.column; } 
        }
 
        internal override ProviderType SqlType { 
            get { return this.column.SqlType; }
        } 

        public override bool Equals(object obj) {
            SqlColumnRef cref = obj as SqlColumnRef;
            return cref != null && cref.Column == this.column; 
        }
 
        public override int GetHashCode() { 
            return this.column.GetHashCode();
        } 

        internal SqlColumn GetRootColumn() {
            SqlColumn c = this.column;
            while (c.Expression != null && c.Expression.NodeType == SqlNodeType.ColumnRef) { 
                c = ((SqlColumnRef)c.Expression).Column;
            } 
            return c; 
        }
    } 

    internal class SqlRow : SqlNode {
        private List columns;
 
        internal SqlRow(Expression sourceExpression)
            : base(SqlNodeType.Row, sourceExpression) { 
            this.columns = new List(); 
        }
 
        internal List Columns {
            get { return this.columns; }
        }
 
        internal SqlColumn Find(string name) {
            foreach (SqlColumn c in this.columns) { 
                if (name == c.Name) 
                    return c;
            } 
            return null;
        }
    }
 
    internal class SqlMemberAssign : SqlNode {
        private MemberInfo member; 
        private SqlExpression expression; 

        internal SqlMemberAssign(MemberInfo member, SqlExpression expr) 
            : base(SqlNodeType.MemberAssign, expr.SourceExpression) {
            if (member == null)
                throw Error.ArgumentNull("member");
            this.member = member; 
            this.Expression = expr;
        } 
 
        internal MemberInfo Member {
            get { return this.member; } 
        }

        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.expression = value;
            } 
        }
    }

    internal class SqlGrouping : SqlSimpleTypeExpression { 
        private SqlExpression key;
        private SqlExpression group; 
 
        internal SqlGrouping(Type clrType, ProviderType sqlType, SqlExpression key, SqlExpression group, Expression sourceExpression)
            : base(SqlNodeType.Grouping, clrType, sqlType, sourceExpression) { 
            if (key == null) throw Error.ArgumentNull("key");
            if (group == null) throw Error.ArgumentNull("group");
            this.key = key;
            this.group = group; 
        }
 
        internal SqlExpression Key { 
            get { return this.key; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (!this.key.ClrType.IsAssignableFrom(value.ClrType)
                    && !value.ClrType.IsAssignableFrom(this.key.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.key.ClrType, value.ClrType);
                this.key = value; 
            } 
        }
 
        internal SqlExpression Group {
            get { return this.group; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (value.ClrType != this.group.ClrType) 
                    throw Error.ArgumentWrongType("value", this.group.ClrType, value.ClrType); 
                this.group = value;
            } 
        }
    }

    internal class SqlNew : SqlSimpleTypeExpression { 
        private MetaType metaType;
        private ConstructorInfo constructor; 
        private List args; 
        private List argMembers;
        private List members; 

        internal SqlNew(MetaType metaType, ProviderType sqlType, ConstructorInfo cons, IEnumerable args, IEnumerable argMembers, IEnumerable members, Expression sourceExpression)
            : base(SqlNodeType.New, metaType.Type, sqlType, sourceExpression) {
            this.metaType = metaType; 

            if (cons == null && metaType.Type.IsClass) { // structs do not need to have a constructor 
                throw Error.ArgumentNull("cons"); 
            }
            this.constructor = cons; 
            this.args = new List();
            this.argMembers = new List();
            this.members = new List();
            if (args != null) { 
                this.args.AddRange(args);
            } 
            if (argMembers != null) { 
                this.argMembers.AddRange(argMembers);
            } 
            if (members != null) {
                this.members.AddRange(members);
            }
        } 

        internal MetaType MetaType { 
            get { return this.metaType; } 
        }
 
        internal ConstructorInfo Constructor {
            get { return this.constructor; }
        }
 
        internal List Args {
            get { return this.args; } 
        } 

        internal List ArgMembers { 
            get { return this.argMembers; }
        }

        internal List Members { 
            get { return this.members; }
        } 
 
        internal SqlExpression Find(MemberInfo mi) {
            for (int i = 0, n = this.argMembers.Count; i < n; i++) { 
                MemberInfo argmi = this.argMembers[i];
                if (argmi.Name == mi.Name) {
                    return this.args[i];
                } 
            }
 
            foreach (SqlMemberAssign ma in this.Members) { 
                if (ma.Member.Name == mi.Name) {
                    return ma.Expression; 
                }
            }

            return null; 
        }
    } 
 
    internal class SqlMethodCall : SqlSimpleTypeExpression {
        private MethodInfo method; 
        private SqlExpression obj;
        private List arguments;

        internal SqlMethodCall(Type clrType, ProviderType sqlType, MethodInfo method, SqlExpression obj, IEnumerable args, Expression sourceExpression) 
            : base(SqlNodeType.MethodCall, clrType, sqlType, sourceExpression) {
            if (method == null) 
                throw Error.ArgumentNull("method"); 
            this.method = method;
            this.Object = obj; 
            this.arguments = new List();
            if (args != null)
                this.arguments.AddRange(args);
        } 

        internal MethodInfo Method { 
            get { return this.method; } 
        }
 
        internal SqlExpression Object {
            get { return this.obj; }
            set {
                if (value == null && !this.method.IsStatic) 
                    throw Error.ArgumentNull("value");
                if (value != null && !this.method.DeclaringType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.method.DeclaringType, value.ClrType); 
                this.obj = value;
            } 
        }

        internal List Arguments {
            get { return this.arguments; } 
        }
    } 
 
    internal class SqlIncludeScope : SqlNode {
        SqlNode child; 
        internal SqlIncludeScope(SqlNode child, Expression sourceExpression)
            : base(SqlNodeType.IncludeScope, sourceExpression) {
            this.child = child;
        } 
        internal SqlNode Child {
            get {return this.child;} 
            set {this.child = value;} 
        }
    } 

    internal class SqlClientArray : SqlSimpleTypeExpression {
        private List expressions;
 
        internal SqlClientArray(Type clrType, ProviderType sqlType, SqlExpression[ ] exprs, Expression sourceExpression)
            : base(SqlNodeType.ClientArray, clrType, sqlType, sourceExpression) { 
            this.expressions = new List(); 
            if (exprs != null)
                this.Expressions.AddRange(exprs); 
        }

        internal List Expressions {
            get { return this.expressions; } 
        }
    } 
 
    internal class SqlLink : SqlSimpleTypeExpression {
        private MetaType rowType; 
        private SqlExpression expression;
        private MetaDataMember member;
        private List keyExpressions;
        private SqlExpression expansion; 
        private object id;
 
        internal SqlLink(object id, MetaType rowType, Type clrType, ProviderType sqlType, SqlExpression expression, MetaDataMember member, IEnumerable keyExpressions, SqlExpression expansion, Expression sourceExpression) 
            : base(SqlNodeType.Link, clrType, sqlType, sourceExpression) {
            this.id = id; 
            this.rowType = rowType;
            this.expansion = expansion;
            this.expression = expression;
            this.member = member; 
            this.keyExpressions = new List();
            if (keyExpressions != null) 
                this.keyExpressions.AddRange(keyExpressions); 
        }
 
        internal MetaType RowType {
            get { return this.rowType; }
        }
 
        internal SqlExpression Expansion {
            get { return this.expansion; } 
            set { this.expansion = value; } 
        }
 

        internal SqlExpression Expression {
            get { return this.expression; }
            set { this.expression = value; } 
        }
 
        internal MetaDataMember Member { 
            get { return this.member; }
        } 

        internal List KeyExpressions {
            get { return this.keyExpressions; }
        } 

        internal object Id { 
            get { return this.id; } 
        }
    } 

    internal class SqlExprSet : SqlExpression {
        private List expressions;
 
        internal SqlExprSet(Type clrType, IEnumerable  exprs, Expression sourceExpression)
            : base(SqlNodeType.ExprSet, clrType, sourceExpression) { 
            this.expressions = new List(exprs); 
        }
 
        internal List Expressions {
            get { return this.expressions; }
        }
 
        /// 
        /// Get the first non-set expression of the set by drilling 
        /// down the left expressions. 
        /// 
        internal SqlExpression GetFirstExpression() { 
            SqlExpression expr = expressions[0];
            while (expr is SqlExprSet) {
                expr = ((SqlExprSet)expr).Expressions[0];
            } 
            return expr;
        } 
 
        internal override ProviderType SqlType {
            get { return this.expressions[0].SqlType; } 
        }
    }

    internal class SqlSubSelect : SqlSimpleTypeExpression { 
        private SqlSelect select;
 
        internal SqlSubSelect(SqlNodeType nt , Type clrType, ProviderType sqlType , SqlSelect select) 
            : base(nt, clrType, sqlType, select.SourceExpression) {
            switch (nt) { 
                case SqlNodeType.Multiset:
                case SqlNodeType.ScalarSubSelect:
                case SqlNodeType.Element:
                case SqlNodeType.Exists: 
                    break;
                default: 
                    throw Error.UnexpectedNode(nt); 
            }
            this.Select = select; 
        }

        internal SqlSelect Select {
            get { return this.select; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.select = value;
            } 
        }
    }

    internal class SqlClientQuery : SqlSimpleTypeExpression { 
        private SqlSubSelect query;
        private List arguments; 
        private List parameters; 
        int ordinal;
 
        internal SqlClientQuery(SqlSubSelect subquery)
            : base(SqlNodeType.ClientQuery, subquery.ClrType, subquery.SqlType, subquery.SourceExpression) {
            this.query = subquery;
            this.arguments = new List(); 
            this.parameters = new List();
        } 
 
        internal SqlSubSelect Query {
            get { return this.query; } 
            set {
                if (value == null || (this.query != null && this.query.ClrType != value.ClrType))
                    throw Error.ArgumentWrongType(value, this.query.ClrType, value.ClrType);
                this.query = value; 
            }
        } 
 
        internal List Arguments {
            get { return this.arguments; } 
        }

        internal List Parameters {
            get { return this.parameters; } 
        }
 
        internal int Ordinal { 
            get { return this.ordinal; }
            set { this.ordinal = value; } 
        }
    }

    internal class SqlJoinedCollection : SqlSimpleTypeExpression { 
        private SqlExpression expression;
        private SqlExpression count; 
 
        internal SqlJoinedCollection(Type clrType, ProviderType sqlType, SqlExpression expression, SqlExpression count, Expression sourceExpression)
            : base(SqlNodeType.JoinedCollection, clrType, sqlType, sourceExpression) { 
            this.expression = expression;
            this.count = count;
        }
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set { 
                if (value == null || this.expression != null && this.expression.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType(value, this.expression.ClrType, value.ClrType); 
                this.expression = value;
            }
        }
 
        internal SqlExpression Count {
            get { return this.count; } 
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (value.ClrType != typeof(int))
                    throw Error.ArgumentWrongType(value, typeof(int), value.ClrType);
                this.count = value;
            } 
        }
    } 
 
    internal class SqlUpdate : SqlStatement {
        private SqlSelect select; 
        private List assignments;

        internal SqlUpdate(SqlSelect select, IEnumerable assignments, Expression sourceExpression)
            : base(SqlNodeType.Update, sourceExpression) { 
            this.Select = select;
            this.assignments = new List(assignments); 
        } 

        internal SqlSelect Select { 
            get { return this.select; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.select = value;
            } 
        } 

        internal List Assignments { 
            get { return this.assignments; }
        }
    }
 
    internal class SqlInsert : SqlStatement {
        private SqlTable table; 
        private SqlRow row; 
        private SqlExpression expression;
        private SqlColumn outputKey; 
        private bool outputToLocal;

        internal SqlInsert(SqlTable table, SqlExpression expr, Expression sourceExpression)
            : base(SqlNodeType.Insert, sourceExpression) { 
            this.Table = table;
            this.Expression = expr; 
            this.Row = new SqlRow(sourceExpression); 
        }
 
        internal SqlTable Table {
            get { return this.table; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("null");
                this.table = value; 
            } 
        }
 
        internal SqlRow Row {
            get { return this.row; }
            set { this.row = value; }
        } 

        internal SqlExpression Expression { 
            get { return this.expression; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("null");
                if (!this.table.RowType.Type.IsAssignableFrom(value.ClrType))
                    throw Error.ArgumentWrongType("value", this.table.RowType, value.ClrType);
                this.expression = value; 
            }
        } 
 
        internal SqlColumn OutputKey {
            get { return this.outputKey; } 
            set { this.outputKey = value; }
        }

        internal bool OutputToLocal { 
            get { return this.outputToLocal; }
            set { this.outputToLocal = value; } 
        } 
    }
 
    internal class SqlDelete : SqlStatement {
        private SqlSelect select;

        internal SqlDelete(SqlSelect select, Expression sourceExpression) 
            : base(SqlNodeType.Delete, sourceExpression) {
            this.Select = select; 
        } 

        internal SqlSelect Select { 
            get { return this.select; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.select = value;
            } 
        } 
    }
 
    internal class SqlBlock : SqlStatement {
        private List statements;

        internal SqlBlock(Expression sourceExpression) 
            : base(SqlNodeType.Block, sourceExpression) {
            this.statements = new List(); 
        } 

        internal List Statements { 
            get { return this.statements; }
        }
    }
 
    internal class SqlAssign : SqlStatement {
        private SqlExpression leftValue; 
        private SqlExpression rightValue; 

        internal SqlAssign(SqlExpression lValue, SqlExpression rValue, Expression sourceExpression) 
            : base(SqlNodeType.Assign, sourceExpression) {
            this.LValue = lValue;
            this.RValue = rValue;
        } 

        internal SqlExpression LValue { 
            get { return this.leftValue; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (this.rightValue != null && !value.ClrType.IsAssignableFrom(this.rightValue.ClrType))
                    throw Error.ArgumentWrongType("value", this.rightValue.ClrType, value.ClrType);
                this.leftValue = value; 
            }
        } 
 
        internal SqlExpression RValue {
            get { return this.rightValue; } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.leftValue != null && !this.leftValue.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.leftValue.ClrType, value.ClrType);
                this.rightValue = value; 
            } 
        }
    } 

    internal class SqlDoNotVisitExpression : SqlExpression {
        private SqlExpression expression;
 
        internal SqlDoNotVisitExpression(SqlExpression expr)
            : base(SqlNodeType.DoNotVisit, expr.ClrType, expr.SourceExpression) { 
            if (expr == null) 
                throw Error.ArgumentNull("expr");
            this.expression = expr; 
        }

        internal SqlExpression Expression {
            get { return this.expression; } 
        }
 
        internal override ProviderType SqlType { 
            get { return this.expression.SqlType; }
        } 
    }

    internal class SqlOptionalValue : SqlSimpleTypeExpression {
        private SqlExpression hasValue; 
        private SqlExpression expressionValue;
 
        internal SqlOptionalValue( SqlExpression hasValue, SqlExpression value) 
            : base(SqlNodeType.OptionalValue, value.ClrType, value.SqlType, value.SourceExpression) {
            this.HasValue = hasValue; 
            this.Value = value;
        }

        internal SqlExpression HasValue { 
            get { return this.hasValue; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                this.hasValue = value; 
            }
        }

        internal SqlExpression Value { 
            get { return this.expressionValue; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (value.ClrType != this.ClrType) 
                    throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                this.expressionValue = value;
            }
        } 
    }
 
    internal class SqlFunctionCall : SqlSimpleTypeExpression { 
        private string name;
        private List arguments; 

        internal SqlFunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable  args , Expression source)
            : this(SqlNodeType.FunctionCall, clrType , sqlType, name, args, source) {
        } 

        internal SqlFunctionCall(SqlNodeType nodeType, Type clrType, ProviderType sqlType, string name , IEnumerable  args , Expression source) 
            : base(nodeType, clrType, sqlType, source) { 
            this.name = name;
            this.arguments = new List(args); 
        }

        internal string Name {
            get { return this.name; } 
        }
 
        internal List Arguments { 
            get { return this.arguments; }
        } 
    }

    /// 
    /// This class is used to represent a table value function.  It inherits normal function 
    /// call functionality, and adds TVF specific members.
    ///  
    internal class SqlTableValuedFunctionCall : SqlFunctionCall { 
        private MetaType rowType;
        private List columns; 

        internal SqlTableValuedFunctionCall(MetaType rowType, Type clrType, ProviderType sqlType, string name, IEnumerable  args , Expression source)
            : base(SqlNodeType.TableValuedFunctionCall, clrType , sqlType, name, args, source) {
            this.rowType = rowType; 
            this.columns = new List();
        } 
 
        internal MetaType RowType {
            get { return this.rowType; } 
        }

        internal List Columns {
            get { return this.columns; } 
        }
 
        internal SqlColumn Find(string name) { 
            foreach (SqlColumn c in this.Columns) {
                if (c.Name == name) 
                    return c;
            }
            return null;
        } 

    } 
 
    internal class SqlSharedExpression : SqlExpression {
        private SqlExpression expr; 

        internal SqlSharedExpression(SqlExpression expr)
          : base(SqlNodeType.SharedExpression, expr.ClrType, expr.SourceExpression) {
            this.expr = expr; 
        }
 
        internal SqlExpression Expression { 
            get { return this.expr; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (!this.ClrType.IsAssignableFrom(value.ClrType)
                    && !value.ClrType.IsAssignableFrom(this.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                this.expr = value; 
            } 
        }
 
        internal override ProviderType SqlType {
            get { return this.expr.SqlType; }
        }
    } 

    internal class SqlSharedExpressionRef : SqlExpression { 
        private SqlSharedExpression expr; 

        internal SqlSharedExpressionRef(SqlSharedExpression expr) 
            : base(SqlNodeType.SharedExpressionRef, expr.ClrType, expr.SourceExpression) {
            this.expr = expr;
        }
 
        internal SqlSharedExpression SharedExpression {
            get { return this.expr; } 
        } 

        internal override ProviderType SqlType { 
            get { return this.expr.SqlType; }
        }
    }
 
    internal class SqlSimpleExpression : SqlExpression {
        private SqlExpression expr; 
 
        internal SqlSimpleExpression(SqlExpression expr)
            : base(SqlNodeType.SimpleExpression, expr.ClrType, expr.SourceExpression) { 
            this.expr = expr;
        }

        internal SqlExpression Expression { 
            get { return this.expr; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (!this.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                this.expr = value;
            }
        } 

        internal override ProviderType SqlType { 
            get { return this.expr.SqlType; } 
        }
    } 

    internal class SqlClientParameter : SqlSimpleTypeExpression {
        // Expression>
        LambdaExpression accessor; 
        internal SqlClientParameter(Type clrType, ProviderType sqlType, LambdaExpression accessor, Expression sourceExpression):
            base(SqlNodeType.ClientParameter, clrType, sqlType, sourceExpression) { 
            this.accessor = accessor; 
        }
        internal LambdaExpression Accessor { 
            get { return this.accessor; }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq.Expressions; 
using System.Diagnostics;
using System.Data; 
 
namespace System.Data.Linq.SqlClient {
    using System.Data.Linq.Mapping; 
    using System.Data.Linq.Provider;
    using System.Diagnostics.CodeAnalysis;

    internal enum SqlNodeType { 
        Add,
        Alias, 
        AliasRef, 
        And,
        Assign, 
        Avg,
        Between,
        BitAnd,
        BitNot, 
        BitOr,
        BitXor, 
        Block, 
        Cast,
        ClientArray, 
        ClientCase,
        ClientParameter,
        ClientQuery,
        ClrLength, 
        Coalesce,
        Column, 
        ColumnRef, 
        Concat,
        Convert, 
        Count,
        Covar,
        Delete,
        DiscriminatedType, 
        DiscriminatorOf,
        Div, 
        DoNotVisit, 
        Element,
        ExprSet, 
        EQ,
        EQ2V,
        Exists,
        FunctionCall, 
        In,
        IncludeScope, 
        IsNotNull, 
        IsNull,
        LE, 
        Lift,
        Link,
        Like,
        LongCount, 
        LT,
        GE, 
        Grouping, 
        GT,
        Insert, 
        Join,
        JoinedCollection,
        Max,
        MethodCall, 
        Member,
        MemberAssign, 
        Min, 
        Mod,
        Mul, 
        Multiset,
        NE,
        NE2V,
        Negate, 
        New,
        Not, 
        Not2V, 
        Nop,
        ObjectType, 
        Or,
        OptionalValue,
        OuterJoinedValue,
        Parameter, 
        Property,
        Row, 
        RowNumber, 
        ScalarSubSelect,
        SearchedCase, 
        Select,
        SharedExpression,
        SharedExpressionRef,
        SimpleCase, 
        SimpleExpression,
        Stddev, 
        StoredProcedureCall, 
        Sub,
        Sum, 
        Table,
        TableValuedFunctionCall,
        Treat,
        TypeCase, 
        Union,
        Update, 
        UserColumn, 
        UserQuery,
        UserRow, 
        Variable,
        Value,
        ValueOf
    } 

    [System.Diagnostics.DebuggerDisplay("text = {Text}, \r\nsource = {SourceExpression}")] 
    internal abstract class SqlNode { 
        private SqlNodeType nodeType;
        private Expression sourceExpression; 

        internal SqlNode(SqlNodeType nodeType, Expression sourceExpression) {
            this.nodeType = nodeType;
            this.sourceExpression = sourceExpression; 
        }
 
        internal Expression SourceExpression { 
            get { return this.sourceExpression; }
        } 

        internal void ClearSourceExpression() {
            this.sourceExpression = null;
        } 

        internal SqlNodeType NodeType { 
            get { return this.nodeType; } 
        }
 
#if DEBUG
        private static DbFormatter formatter;
        internal static DbFormatter Formatter {
            get { return formatter; } 
            set { formatter = value; }
        } 
 
        internal string Text {
            get { 
                if (Formatter == null)
                    return "SqlNode.Formatter is not assigned";
                return SqlNode.Formatter.Format(this, true);
            } 
        }
#endif 
    } 

    internal abstract class SqlExpression : SqlNode { 
        private Type clrType;
        internal SqlExpression(SqlNodeType nodeType, Type clrType, Expression sourceExpression)
            : base(nodeType, sourceExpression) {
            this.clrType = clrType; 
        }
 
        internal Type ClrType { 
            get { return this.clrType; }
        } 

        // note: changing the CLR type of a node is potentially dangerous
        internal void SetClrType(Type type) {
            this.clrType = type; 
        }
 
        internal abstract ProviderType SqlType { get; } 

        ///  
        /// Drill down looking for a constant root expression, returning true if found.
        /// 
        internal bool IsConstantColumn {
            get { 
                if (this.NodeType == SqlNodeType.Column) {
                    SqlColumn col = (SqlColumn)this; 
                    if (col.Expression != null) { 
                        return col.Expression.IsConstantColumn;
                    } 
                }
                else if (this.NodeType == SqlNodeType.ColumnRef) {
                    return ((SqlColumnRef)this).Column.IsConstantColumn;
                } 
                else if (this.NodeType == SqlNodeType.OptionalValue) {
                    return ((SqlOptionalValue)this).Value.IsConstantColumn; 
                } 
                else if (this.NodeType == SqlNodeType.Value ||
                        this.NodeType == SqlNodeType.Parameter) { 
                    return true;
                }
                return false;
            } 
        }
    } 
 
    /// 
    /// A SqlExpression with a simple implementation of ClrType and SqlType. 
    /// 
    internal abstract class SqlSimpleTypeExpression : SqlExpression {
        private ProviderType sqlType;
 
        internal SqlSimpleTypeExpression(SqlNodeType nodeType, Type clrType, ProviderType sqlType, Expression sourceExpression)
            : base(nodeType, clrType, sourceExpression) { 
            this.sqlType = sqlType; 
        }
 
        internal override ProviderType SqlType {
            get { return this.sqlType; }
        }
 
        internal void SetSqlType(ProviderType type) {
            this.sqlType = type; 
        } 
    }
 
    /// 
    /// Represents the dynamic CLR type of the given object. Equivalent to obj.GetType().
    /// 
    internal class SqlObjectType : SqlExpression { 
        SqlExpression obj;
        ProviderType sqlType; 
        internal SqlObjectType(SqlExpression obj, ProviderType sqlType, Expression sourceExpression) 
            : base(SqlNodeType.ObjectType,
                   typeof(Type),  // Want this to be typeof(RuntimeType) which is the true implementation of the abstract typeof(Type) 
                   sourceExpression) {
            this.obj = obj;
            this.sqlType = sqlType;
        } 
        internal SqlExpression Object {
            set { this.obj = value; } 
            get { return this.obj; } 
        }
        internal override ProviderType SqlType { 
            get { return this.sqlType; }
        }
        internal void SetSqlType(ProviderType type) {
            this.sqlType = type; 
        }
    } 
 
    internal class SqlDiscriminatorOf : SqlSimpleTypeExpression {
        SqlExpression obj; 
        internal SqlDiscriminatorOf(SqlExpression obj, Type clrType, ProviderType sqlType, Expression sourceExpression)
            : base(SqlNodeType.DiscriminatorOf, clrType, sqlType, sourceExpression) {
            this.obj = obj;
        } 
        internal SqlExpression Object {
            get { return this.obj; } 
            set { this.obj = value; } 
        }
    } 


    /// 
    /// Represents a dynamic CLR type that is chosen based on a discriminator expression. 
    /// 
    internal class SqlDiscriminatedType : SqlExpression { 
        private ProviderType sqlType; 
        private SqlExpression discriminator;
        private MetaType targetType; 
        internal SqlDiscriminatedType(ProviderType sqlType, SqlExpression discriminator, MetaType targetType, Expression sourceExpression)
            : base(SqlNodeType.DiscriminatedType,
                   typeof(Type),
                   sourceExpression) { 
            if (discriminator == null)
                throw Error.ArgumentNull("discriminator"); 
            this.discriminator = discriminator; 
            this.targetType = targetType;
            this.sqlType = sqlType; 
        }
        internal override ProviderType SqlType {
            get { return this.sqlType; }
        } 
        internal SqlExpression Discriminator {
            get { return this.discriminator; } 
            set { this.discriminator = value; } 
        }
 
        internal MetaType TargetType {
            get { return this.targetType; }
        }
    } 

    internal abstract class SqlStatement : SqlNode { 
        internal SqlStatement(SqlNodeType nodeType, Expression sourceExpression) 
            : base(nodeType, sourceExpression) {
        } 
    }

    internal abstract class SqlSource : SqlNode {
        internal SqlSource(SqlNodeType nt, Expression sourceExpression) 
            : base(nt, sourceExpression) {
        } 
    } 

    internal class SqlSelect : SqlStatement { 
        private SqlExpression top;
        private bool isPercent;
        private bool isDistinct;
        private SqlExpression selection; 
        private SqlRow row;
        private SqlSource from; 
        private SqlExpression where; 
        private List groupBy;
        private SqlExpression having; 
        private List orderBy;
        private SqlOrderingType orderingType;
        private bool squelch;
 
        internal SqlSelect(SqlExpression selection, SqlSource from, Expression sourceExpression)
            : base(SqlNodeType.Select, sourceExpression) { 
            this.Row = new SqlRow(sourceExpression); 
            this.Selection = selection;
            this.From = from; 
            this.groupBy = new List();
            this.orderBy = new List();
            this.orderingType = SqlOrderingType.Default;
        } 

        internal SqlExpression Top { 
            get { return this.top; } 
            set { this.top = value; }
        } 

        internal bool IsPercent {
            get { return this.isPercent; }
            set { this.isPercent = value; } 
        }
 
        internal bool IsDistinct { 
            get { return this.isDistinct; }
            set { this.isDistinct = value; } 
        }

        internal SqlExpression Selection {
            get { return this.selection; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.selection = value;
            } 
        }

        internal SqlRow Row {
            get { return this.row; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.row = value;
            } 
        }

        internal SqlSource From {
            get { return this.from; } 
            set { this.from = value; }
        } 
 
        internal SqlExpression Where {
            get { return this.where; } 
            set {
                if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) {
                    throw Error.ArgumentWrongType("value", "bool", value.ClrType);
                } 
                this.where = value;
            } 
        } 

        internal List GroupBy { 
            get { return this.groupBy; }
        }

        internal SqlExpression Having { 
            get { return this.having; }
            set { 
                if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) { 
                    throw Error.ArgumentWrongType("value", "bool", value.ClrType);
                } 
                this.having = value;
            }
        }
 
        internal List OrderBy {
            get { return this.orderBy; } 
        } 

        internal SqlOrderingType OrderingType { 
            get { return this.orderingType; }
            set { this.orderingType = value; }
        }
 
        internal bool DoNotOutput {
            get { return this.squelch; } 
            set { this.squelch = value; } 
        }
    } 

    internal enum SqlOrderingType {
        Default,
        Never, 
        Blocked,
        Always 
    } 

    internal class SqlTable : SqlNode { 
        private MetaTable table;
        private MetaType rowType;
        private ProviderType sqlRowType;
        private List columns; 

        internal SqlTable(MetaTable table, MetaType rowType, ProviderType sqlRowType, Expression sourceExpression) 
            : base(SqlNodeType.Table, sourceExpression) { 
            this.table = table;
            this.rowType = rowType; 
            this.sqlRowType = sqlRowType;
            this.columns = new List();
        }
 
        internal MetaTable MetaTable {
            get { return this.table; } 
        } 

        internal string Name { 
            get { return this.table.TableName; }
        }

        internal List Columns { 
            get { return this.columns; }
        } 
 
        internal MetaType RowType {
            get { return this.rowType; } 
        }

        internal ProviderType SqlRowType {
            get { return this.sqlRowType; } 
        }
 
        internal SqlColumn Find(string columnName) { 
            foreach (SqlColumn c in this.Columns) {
                if (c.Name == columnName) 
                    return c;
            }
            return null;
        } 

    } 
 
    internal class SqlUserQuery : SqlNode {
        private string queryText; 
        private SqlExpression projection;
        private List args;
        private List columns;
 
        internal SqlUserQuery(SqlNodeType nt, SqlExpression projection, IEnumerable args, Expression source)
            : base(nt, source) { 
            this.Projection = projection; 
            this.args = (args != null) ? new List(args) : new List();
            this.columns = new List(); 
        }

        internal SqlUserQuery(string queryText, SqlExpression projection, IEnumerable args, Expression source)
            : base(SqlNodeType.UserQuery, source) { 
            this.queryText = queryText;
            this.Projection = projection; 
            this.args = (args != null) ? new List(args) : new List(); 
            this.columns = new List();
        } 

        internal string QueryText {
            get { return this.queryText; }
        } 

        internal SqlExpression Projection { 
            get { return this.projection; } 
            set {
                if (this.projection != null && this.projection.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.projection.ClrType, value.ClrType);
                this.projection = value;
            }
        } 

        internal List Arguments { 
            get { return this.args; } 
        }
 
        internal List Columns {
            get { return this.columns; }
        }
 
        internal SqlUserColumn Find(string name) {
            foreach (SqlUserColumn c in this.Columns) { 
                if (c.Name == name) 
                    return c;
            } 
            return null;
        }
    }
 
    internal class SqlStoredProcedureCall : SqlUserQuery {
        private MetaFunction function; 
 
        internal SqlStoredProcedureCall(MetaFunction function, SqlExpression projection, IEnumerable args, Expression source)
            : base(SqlNodeType.StoredProcedureCall, projection, args, source) { 
            if (function == null)
                throw Error.ArgumentNull("function");
            this.function = function;
        } 

        internal MetaFunction Function { 
            get { return this.function; } 
        }
    } 

    internal class SqlUserRow : SqlSimpleTypeExpression {
        private SqlUserQuery query;
        private MetaType rowType; 

        internal SqlUserRow(MetaType rowType, ProviderType sqlType, SqlUserQuery query, Expression source) 
            : base(SqlNodeType.UserRow, rowType.Type, sqlType, source) { 
            this.Query = query;
            this.rowType = rowType; 
        }

        internal MetaType RowType {
            get { return this.rowType; } 
        }
 
        internal SqlUserQuery Query { 
            get { return this.query; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (value.Projection != null && value.Projection.ClrType != this.ClrType)
                    throw Error.ArgumentWrongType("value", this.ClrType, value.Projection.ClrType); 
                this.query = value;
            } 
        } 
    }
 
    internal class SqlUserColumn : SqlSimpleTypeExpression {
        private SqlUserQuery query;
        private string name;
        private bool isRequired; 

        internal SqlUserColumn(Type clrType, ProviderType sqlType, SqlUserQuery query, string name, bool isRequired, Expression source) 
            : base(SqlNodeType.UserColumn, clrType, sqlType, source) { 
            this.Query = query;
            this.name = name; 
            this.isRequired = isRequired;
        }

        internal SqlUserQuery Query { 
            get { return this.query; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (this.query != null && this.query != value) 
                    throw Error.ArgumentWrongValue("value");
                this.query = value;
            }
        } 

        internal string Name { 
            get { return this.name; } 
        }
 
        internal bool IsRequired {
            get { return this.isRequired; }
        }
    } 

    internal class SqlAlias : SqlSource { 
        private string name; 
        private SqlNode node;
 
        internal SqlAlias(SqlNode node)
            : base(SqlNodeType.Alias, node.SourceExpression) {
            this.Node = node;
        } 

        internal string Name { 
            get { return this.name; } 
            set { this.name = value; }
        } 

        internal SqlNode Node {
            get { return this.node; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (!(value is SqlExpression || value is SqlSelect || value is SqlTable || value is SqlUnion)) 
                    throw Error.UnexpectedNode(value.NodeType);
                this.node = value; 
            }
        }
    }
 
    internal class SqlAliasRef : SqlExpression {
        private SqlAlias alias; 
 
        internal SqlAliasRef(SqlAlias alias)
            : base(SqlNodeType.AliasRef, GetClrType(alias.Node), alias.SourceExpression) { 
            if (alias == null)
                throw Error.ArgumentNull("alias");
            this.alias = alias;
        } 

        internal SqlAlias Alias { 
            get { return this.alias; } 
        }
 
        internal override ProviderType SqlType {
            get { return GetSqlType(this.alias.Node); }
        }
 
        private static Type GetClrType(SqlNode node) {
            SqlTableValuedFunctionCall tvf = node as SqlTableValuedFunctionCall; 
            if (tvf != null) 
                return tvf.RowType.Type;
            SqlExpression exp = node as SqlExpression; 
            if (exp != null) {
                if (TypeSystem.IsSequenceType(exp.ClrType))
                    return TypeSystem.GetElementType(exp.ClrType);
                return exp.ClrType; 
            }
            SqlSelect sel = node as SqlSelect; 
            if (sel != null) 
                return sel.Selection.ClrType;
            SqlTable tab = node as SqlTable; 
            if (tab != null)
                return tab.RowType.Type;
            SqlUnion su = node as SqlUnion;
            if (su != null) 
                return su.GetClrType();
            throw Error.UnexpectedNode(node.NodeType); 
        } 

        private static ProviderType GetSqlType(SqlNode node) { 
            SqlExpression exp = node as SqlExpression;
            if (exp != null)
                return exp.SqlType;
            SqlSelect sel = node as SqlSelect; 
            if (sel != null)
                return sel.Selection.SqlType; 
            SqlTable tab = node as SqlTable; 
            if (tab != null)
                return tab.SqlRowType; 
            SqlUnion su = node as SqlUnion;
            if (su != null)
                return su.GetSqlType();
            throw Error.UnexpectedNode(node.NodeType); 
        }
    } 
 
    internal class SqlJoin : SqlSource {
        private SqlJoinType joinType; 
        private SqlSource left;
        private SqlSource right;
        private SqlExpression condition;
 
        internal SqlJoin(SqlJoinType type, SqlSource left, SqlSource right, SqlExpression cond, Expression sourceExpression)
            : base(SqlNodeType.Join, sourceExpression) { 
            this.JoinType = type; 
            this.Left = left;
            this.Right = right; 
            this.Condition = cond;
        }

        internal SqlJoinType JoinType { 
            get { return this.joinType; }
            set { this.joinType = value; } 
        } 

        internal SqlSource Left { 
            get { return this.left; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.left = value;
            } 
        } 

        internal SqlSource Right { 
            get { return this.right; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.right = value;
            } 
        } 

        internal SqlExpression Condition { 
            get { return this.condition; }
            set { this.condition = value; }
        }
    } 

    internal enum SqlJoinType { 
        Cross, 
        Inner,
        LeftOuter, 
        CrossApply,
        OuterApply
    }
 
    internal class SqlUnion : SqlNode {
        private SqlNode left; 
        private SqlNode right; 
        private bool all;
 
        internal SqlUnion(SqlNode left, SqlNode right, bool all)
            : base(SqlNodeType.Union, right.SourceExpression) {
            this.Left = left;
            this.Right = right; 
            this.All = all;
        } 
 
        internal SqlNode Left {
            get { return this.left; } 
            set {
                Validate(value);
                this.left = value;
            } 
        }
 
        internal SqlNode Right { 
            get { return this.right; }
            set { 
                Validate(value);
                this.right = value;
            }
        } 

        internal bool All { 
            get { return this.all; } 
            set { this.all = value; }
        } 

        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
        private void Validate(SqlNode node) {
            if (node == null) 
                throw Error.ArgumentNull("node");
            if (!(node is SqlExpression || node is SqlSelect || node is SqlUnion)) 
                throw Error.UnexpectedNode(node.NodeType); 
        }
 
        internal Type GetClrType() {
            SqlExpression exp = this.Left as SqlExpression;
            if (exp != null)
                return exp.ClrType; 
            SqlSelect sel = this.Left as SqlSelect;
            if (sel != null) 
                return sel.Selection.ClrType; 
            throw Error.CouldNotGetClrType();
        } 

        internal ProviderType GetSqlType() {
            SqlExpression exp = this.Left as SqlExpression;
            if (exp != null) 
                return exp.SqlType;
            SqlSelect sel = this.Left as SqlSelect; 
            if (sel != null) 
                return sel.Selection.SqlType;
            throw Error.CouldNotGetSqlType(); 
        }
    }

    internal class SqlNop : SqlSimpleTypeExpression { 
        internal SqlNop(Type clrType, ProviderType sqlType, Expression sourceExpression)
            : base(SqlNodeType.Nop, clrType, sqlType, sourceExpression) { 
        } 
    }
 
    internal class SqlLift : SqlExpression {
        internal SqlExpression liftedExpression;

        internal SqlLift(Type type, SqlExpression liftedExpression, Expression sourceExpression) 
            : base(SqlNodeType.Lift, type, sourceExpression) {
            if (liftedExpression == null) 
                throw Error.ArgumentNull("liftedExpression"); 
            this.liftedExpression = liftedExpression;
        } 

        internal SqlExpression Expression {
            get { return this.liftedExpression; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.liftedExpression = value; 
            }
        } 

        internal override ProviderType SqlType {
            get { return this.liftedExpression.SqlType; }
        } 
    }
 
    internal enum SqlOrderType { 
        Ascending,
        Descending 
    }

    internal class SqlOrderExpression : IEquatable {
        private SqlOrderType orderType; 
        private SqlExpression expression;
 
        internal SqlOrderExpression(SqlOrderType type, SqlExpression expr) { 
            this.OrderType = type;
            this.Expression = expr; 
        }

        internal SqlOrderType OrderType {
            get { return this.orderType; } 
            set { this.orderType = value; }
        } 
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.expression != null && !this.expression.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
                this.expression = value; 
            } 
        }
 
        public override bool Equals(object obj) {
            if (this.EqualsTo(obj as SqlOrderExpression))
                return true;
 
            return base.Equals(obj);
        } 
 
        public bool Equals(SqlOrderExpression other) {
            if (this.EqualsTo(other)) 
                return true;

            return base.Equals(other);
        } 

        private bool EqualsTo(SqlOrderExpression other) { 
            if (other == null) 
                return false;
            if (object.ReferenceEquals(this, other)) 
                return true;
            if (this.OrderType != other.OrderType)
                return false;
            if (!this.Expression.SqlType.Equals(other.Expression.SqlType)) 
                return false;
 
            SqlColumn col1 = SqlOrderExpression.UnwrapColumn(this.Expression); 
            SqlColumn col2 = SqlOrderExpression.UnwrapColumn(other.Expression);
 
            if (col1 == null || col2 == null)
                return false;

            return col1 == col2; 
        }
 
        public override int GetHashCode() { 
            SqlColumn col = SqlOrderExpression.UnwrapColumn(this.Expression);
            if (col != null) 
                return col.GetHashCode();

            return base.GetHashCode();
        } 

        private static SqlColumn UnwrapColumn(SqlExpression expr) { 
            System.Diagnostics.Debug.Assert(expr != null); 

            if (expr is SqlUnary) 
                expr = ((SqlUnary)expr).Operand;
            if (expr is SqlColumn)
                return expr as SqlColumn;
            if (expr is SqlColumnRef) 
                return ((SqlColumnRef)expr).GetRootColumn();
            // 
            // For all other types return null to revert to default behavior for Equals() 
            // and GetHashCode()
            // 
            return null;
        }
    }
 
    internal class SqlRowNumber : SqlSimpleTypeExpression {
        private List orderBy; 
 
        internal List OrderBy {
            get { return orderBy; } 
        }

        internal SqlRowNumber(Type clrType, ProviderType sqlType, List orderByList, Expression sourceExpression)
            : base(SqlNodeType.RowNumber, clrType, sqlType, sourceExpression) { 
            if (orderByList == null) {
                throw Error.ArgumentNull("orderByList"); 
            } 

            this.orderBy = orderByList; 
        }
    }

    internal class SqlUnary : SqlSimpleTypeExpression { 
        private SqlExpression operand;
        private MethodInfo method; 
 
        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
        internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, Expression sourceExpression) 
            : this(nt, clrType, sqlType, expr, null, sourceExpression) {
        }

        internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, MethodInfo method, Expression sourceExpression) 
            : base(nt, clrType, sqlType, sourceExpression) {
            switch (nt) { 
                case SqlNodeType.Not: 
                case SqlNodeType.Not2V:
                case SqlNodeType.Negate: 
                case SqlNodeType.BitNot:
                case SqlNodeType.IsNull:
                case SqlNodeType.IsNotNull:
                case SqlNodeType.Count: 
                case SqlNodeType.LongCount:
                case SqlNodeType.Max: 
                case SqlNodeType.Min: 
                case SqlNodeType.Sum:
                case SqlNodeType.Avg: 
                case SqlNodeType.Stddev:
                case SqlNodeType.Covar:
                case SqlNodeType.Convert:
                case SqlNodeType.ValueOf: 
                case SqlNodeType.Cast:
                case SqlNodeType.Treat: 
                case SqlNodeType.OuterJoinedValue: 
                case SqlNodeType.ClrLength:
                    break; 
                default:
                    throw Error.UnexpectedNode(nt);
            }
            this.Operand = expr; 
            this.method = method;
        } 
 
        internal SqlExpression Operand {
            get { return this.operand; } 
            set {
                if (value == null && (this.NodeType != SqlNodeType.Count && this.NodeType != SqlNodeType.LongCount))
                    throw Error.ArgumentNull("value");
                this.operand = value; 
            }
        } 
 
        internal MethodInfo Method {
            get { return this.method; } 
        }
    }

    internal class SqlBinary : SqlSimpleTypeExpression { 
        private SqlExpression left;
        private SqlExpression right; 
        private MethodInfo method; 

        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")] 
        internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right)
            : this(nt, clrType, sqlType, left, right, null) {
        }
 
        internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method)
            : base(nt, clrType, sqlType, right.SourceExpression) { 
            switch (nt) { 
                case SqlNodeType.Add:
                case SqlNodeType.Sub: 
                case SqlNodeType.Mul:
                case SqlNodeType.Div:
                case SqlNodeType.Mod:
                case SqlNodeType.BitAnd: 
                case SqlNodeType.BitOr:
                case SqlNodeType.BitXor: 
                case SqlNodeType.And: 
                case SqlNodeType.Or:
                case SqlNodeType.GE: 
                case SqlNodeType.GT:
                case SqlNodeType.LE:
                case SqlNodeType.LT:
                case SqlNodeType.EQ: 
                case SqlNodeType.NE:
                case SqlNodeType.EQ2V: 
                case SqlNodeType.NE2V: 
                case SqlNodeType.Concat:
                case SqlNodeType.Coalesce: 
                    break;
                default:
                    throw Error.UnexpectedNode(nt);
            } 
            this.Left = left;
            this.Right = right; 
            this.method = method; 
        }
 
        internal SqlExpression Left {
            get { return this.left; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                this.left = value; 
            } 
        }
 
        internal SqlExpression Right {
            get { return this.right; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                this.right = value; 
            } 
        }
 
        internal MethodInfo Method {
            get { return this.method; }
        }
    } 

    internal class SqlBetween : SqlSimpleTypeExpression { 
        SqlExpression expression; 
        SqlExpression start;
        SqlExpression end; 

        internal SqlBetween(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression start, SqlExpression end, Expression source)
            : base(SqlNodeType.Between, clrType, sqlType, source) {
            this.expression = expr; 
            this.start = start;
            this.end = end; 
        } 

        internal SqlExpression Expression { 
            get { return this.expression; }
            set { this.expression = value; }
        }
 
        internal SqlExpression Start {
            get { return this.start; } 
            set { this.start = value; } 
        }
 
        internal SqlExpression End {
            get { return this.end; }
            set { this.end = value; }
        } 
    }
 
    internal class SqlIn : SqlSimpleTypeExpression { 
        private SqlExpression expression;
        private List values; 

        internal SqlIn(Type clrType, ProviderType sqlType, SqlExpression expression, IEnumerable values, Expression sourceExpression)
            :base(SqlNodeType.In, clrType, sqlType, sourceExpression) {
            this.expression = expression; 
            this.values = values != null ? new List(values) : new List(0);
        } 
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null) {
                    throw Error.ArgumentNull("value");
                } 
                this.expression = value;
            } 
        } 
        internal List Values {
            get { return this.values; } 
        }
    }

    internal class SqlLike : SqlSimpleTypeExpression { 
        private SqlExpression expression;
        private SqlExpression pattern; 
        private SqlExpression escape; 

        internal SqlLike(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression pattern, SqlExpression escape, Expression source) 
            : base(SqlNodeType.Like, clrType, sqlType, source) {
            if (expr == null)
                throw Error.ArgumentNull("expr");
            if (pattern == null) 
                throw Error.ArgumentNull("pattern");
            this.Expression = expr; 
            this.Pattern = pattern; 
            this.Escape = escape;
        } 

        internal SqlExpression Expression {
            get { return this.expression; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (value.ClrType != typeof(string)) 
                    throw Error.ArgumentWrongType("value", "string", value.ClrType);
                this.expression = value; 
            }
        }

        internal SqlExpression Pattern { 
            get { return this.pattern; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (value.ClrType != typeof(string)) 
                    throw Error.ArgumentWrongType("value", "string", value.ClrType);
                this.pattern = value;
            }
        } 

        internal SqlExpression Escape { 
            get { return this.escape; } 
            set {
                if (value != null && value.ClrType != typeof(string)) 
                    throw Error.ArgumentWrongType("value", "string", value.ClrType);
                this.escape = value;
            }
        } 
    }
 
    internal class SqlWhen { 
        private SqlExpression matchExpression;
        private SqlExpression valueExpression; 

        internal SqlWhen(SqlExpression match, SqlExpression value) {
            // 'match' may be null when this when represents the ELSE condition.
            if (value == null) 
                throw Error.ArgumentNull("value");
            this.Match = match; 
            this.Value = value; 
        }
 
        internal SqlExpression Match {
            get { return this.matchExpression; }
            set {
                if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
                this.matchExpression = value; 
            } 
        }
 
        internal SqlExpression Value {
            get { return this.valueExpression; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (this.valueExpression != null && !this.valueExpression.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.valueExpression.ClrType, value.ClrType); 
                this.valueExpression = value;
            } 
        }
    }

    /* 
     * Searched CASE function:
     * CASE 
     * WHEN BooleanExpression THEN resultExpression 
     * [ ...n ]
     * [ 
     * ELSE elseResultExpression
     * ]
     * END
     */ 
    internal class SqlSearchedCase : SqlExpression {
        private List whens; 
        private SqlExpression @else; 

        internal SqlSearchedCase(Type clrType, IEnumerable whens, SqlExpression @else, Expression sourceExpression) 
            : base(SqlNodeType.SearchedCase, clrType, sourceExpression) {
            if (whens == null)
                throw Error.ArgumentNull("whens");
            this.whens = new List(whens); 
            if (this.whens.Count == 0)
                throw Error.ArgumentOutOfRange("whens"); 
            this.Else = @else; 
        }
 
        internal List Whens {
            get { return this.whens; }
        }
 
        internal SqlExpression Else {
            get { return this.@else; } 
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (this.@else != null && !this.@else.ClrType.IsAssignableFrom(value.ClrType))
                    throw Error.ArgumentWrongType("value", this.@else.ClrType, value.ClrType);
                this.@else = value;
            } 
        }
 
        internal override ProviderType SqlType { 
            get { return this.whens[0].Value.SqlType; }
        } 
    }

    /*
     * Simple CASE function: 
     * CASE inputExpression
     * WHEN whenExpression THEN resultExpression 
     * [ ...n ] 
     * [
     * ELSE elseResultExpression 
     * ]
     * END
     */
    internal class SqlSimpleCase : SqlExpression { 
        private SqlExpression expression;
        private List whens = new List(); 
 
        internal SqlSimpleCase(Type clrType, SqlExpression expr, IEnumerable whens, Expression sourceExpression)
            : base(SqlNodeType.SimpleCase, clrType, sourceExpression) { 
            this.Expression = expr;
            if (whens == null)
                throw Error.ArgumentNull("whens");
            this.whens.AddRange(whens); 
            if (this.whens.Count == 0)
                throw Error.ArgumentOutOfRange("whens"); 
        } 

        internal SqlExpression Expression { 
            get { return this.expression; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (this.expression != null && this.expression.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType); 
                this.expression = value; 
            }
        } 

        internal List Whens {
            get { return this.whens; }
        } 

        internal override ProviderType SqlType { 
            get { return this.whens[0].Value.SqlType; } 
        }
    } 

    /// 
    /// A case statement that must be evaluated on the client. For example, a case statement
    /// that contains values of LINK, Element, or Multi-set are not directly handleable by 
    /// SQL.
    /// 
    /// CASE inputExpression 
    /// WHEN whenExpression THEN resultExpression
    /// [ ...n ] 
    /// END
    /// 
    internal class SqlClientCase : SqlExpression {
        private SqlExpression expression; 
        private List whens = new List();
 
        internal SqlClientCase(Type clrType, SqlExpression expr, IEnumerable whens, Expression sourceExpression) 
            : base(SqlNodeType.ClientCase, clrType, sourceExpression) {
            this.Expression = expr; 
            if (whens == null)
                throw Error.ArgumentNull("whens");
            this.whens.AddRange(whens);
            if (this.whens.Count == 0) 
                throw Error.ArgumentOutOfRange("whens");
        } 
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.expression != null && this.expression.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
                this.expression = value; 
            } 
        }
 
        internal List Whens {
            get { return this.whens; }
        }
 
        internal override ProviderType SqlType {
            get { return this.whens[0].Value.SqlType; } 
        } 
    }
 
    /// 
    /// A single WHEN clause for ClientCase.
    /// 
    internal class SqlClientWhen { 
        private SqlExpression matchExpression;
        private SqlExpression matchValue; 
 
        internal SqlClientWhen(SqlExpression match, SqlExpression value) {
            // 'match' may be null when this when represents the ELSE condition. 
            if (value == null)
                throw Error.ArgumentNull("value");
            this.Match = match;
            this.Value = value; 
        }
 
        internal SqlExpression Match { 
            get { return this.matchExpression; }
            set { 
                if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
                this.matchExpression = value;
            } 
        }
 
        internal SqlExpression Value { 
            get { return this.matchValue; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.matchValue != null && this.matchValue.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.matchValue.ClrType, value.ClrType); 
                this.matchValue = value;
            } 
        } 
    }
 
    /// 
    /// Represents the construction of an object in abstract 'super sql'.
    /// The type may be polymorphic. A discriminator field is used to determine
    /// which type in a hierarchy should be instantiated. 
    /// In the common degenerate case where the inheritance hierarchy is 1-deep
    /// the discriminator will be a constant SqlValue and there will be one 
    /// type-case-when corresponding to that type. 
    /// 
    internal class SqlTypeCase : SqlExpression { 
        private MetaType rowType;
        private SqlExpression discriminator;
        private List whens = new List();
        ProviderType sqlType; 

        internal SqlTypeCase(Type clrType, ProviderType sqlType, MetaType rowType, SqlExpression discriminator, IEnumerable whens, Expression sourceExpression) 
            : base(SqlNodeType.TypeCase, clrType, sourceExpression) { 
            this.Discriminator = discriminator;
            if (whens == null) 
                throw Error.ArgumentNull("whens");
            this.whens.AddRange(whens);
            if (this.whens.Count == 0)
                throw Error.ArgumentOutOfRange("whens"); 
            this.sqlType = sqlType;
            this.rowType = rowType; 
        } 

        internal SqlExpression Discriminator { 
            get { return this.discriminator; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (this.discriminator != null && this.discriminator.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType("value", this.discriminator.ClrType, value.ClrType); 
                this.discriminator = value; 
            }
        } 

        internal List Whens {
            get { return this.whens; }
        } 

        internal override ProviderType SqlType { 
            get { return sqlType; } 
        }
 
        internal MetaType RowType {
            get { return this.rowType; }
        }
    } 

    ///  
    /// Represents one choice of object instantiation type in a type case. 
    /// When 'match' is the same as type case Discriminator then the corresponding
    /// type binding is the one used for instantiation. 
    /// 
    internal class SqlTypeCaseWhen {
        private SqlExpression match;
        private SqlExpression @new; 

        internal SqlTypeCaseWhen(SqlExpression match, SqlExpression typeBinding) { 
            this.Match = match; 
            this.TypeBinding = typeBinding;
        } 
        internal SqlExpression Match {
            get { return this.match; }
            set {
                if (this.match != null && value != null && this.match.ClrType != value.ClrType) 
                    throw Error.ArgumentWrongType("value", this.match.ClrType, value.ClrType);
                this.match = value; 
            } 
        }
        internal SqlExpression TypeBinding { 
            get { return this.@new; }
            set { this.@new = value; }
        }
    } 

    internal class SqlValue : SqlSimpleTypeExpression { 
        private object value; 
        private bool isClient;
 
        internal SqlValue(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression)
            : base(SqlNodeType.Value, clrType, sqlType, sourceExpression) {
            this.value = value;
            this.isClient = isClientSpecified; 
        }
 
        internal object Value { 
            get { return this.value; }
        } 

        internal bool IsClientSpecified {
            get { return this.isClient; }
        } 
    }
 
    internal class SqlParameter : SqlSimpleTypeExpression { 
        private string name;
        private System.Data.ParameterDirection direction; 

        internal SqlParameter(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)
            : base(SqlNodeType.Parameter, clrType, sqlType, sourceExpression) {
            if (name == null) 
                throw Error.ArgumentNull("name");
            if (typeof(Type).IsAssignableFrom(clrType)) 
                throw Error.ArgumentWrongValue("clrType"); 
            this.name = name;
            this.direction = System.Data.ParameterDirection.Input; 
        }

        internal string Name {
            get { return this.name; } 
        }
 
        internal System.Data.ParameterDirection Direction { 
            get { return this.direction; }
            set { this.direction = value; } 
        }
    }

    internal class SqlVariable : SqlSimpleTypeExpression { 
        private string name;
 
        internal SqlVariable(Type clrType, ProviderType sqlType, string name, Expression sourceExpression) 
            : base(SqlNodeType.Variable, clrType, sqlType, sourceExpression) {
            if (name == null) 
                throw Error.ArgumentNull("name");
            this.name = name;
        }
 
        internal string Name {
            get { return this.name; } 
        } 
    }
 
    internal class SqlMember : SqlSimpleTypeExpression {
        private SqlExpression expression;
        private MemberInfo member;
 
        internal SqlMember(Type clrType, ProviderType sqlType, SqlExpression expr, MemberInfo member)
            : base(SqlNodeType.Member, clrType, sqlType, expr.SourceExpression) { 
            this.member = member; 
            this.Expression = expr;
        } 

        internal MemberInfo Member {
            get { return this.member; }
        } 

        internal SqlExpression Expression { 
            get { 
                return this.expression;
            } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (!this.member.ReflectedType.IsAssignableFrom(value.ClrType) && 
                    !value.ClrType.IsAssignableFrom(this.member.ReflectedType))
                    throw Error.MemberAccessIllegal(this.member, this.member.ReflectedType, value.ClrType); 
                this.expression = value; 
            }
        } 
    }

    internal class SqlColumn : SqlExpression {
        private SqlAlias alias; 
        private string name;
        private int ordinal; 
        private MetaDataMember member; 
        private SqlExpression expression;
        private ProviderType sqlType; 

        internal SqlColumn(Type clrType, ProviderType sqlType, string name, MetaDataMember member, SqlExpression expr, Expression sourceExpression)
            : base(SqlNodeType.Column, clrType, sourceExpression) {
            if (typeof(Type).IsAssignableFrom(clrType)) 
                throw Error.ArgumentWrongValue("clrType");
            this.Name = name; 
            this.member = member; 
            this.Expression = expr;
            this.Ordinal = -1; 
            if (sqlType == null)
                throw Error.ArgumentNull("sqlType");
            this.sqlType = sqlType;
            System.Diagnostics.Debug.Assert(sqlType.CanBeColumn); 
        }
 
        internal SqlColumn(string name, SqlExpression expr) 
            : this(expr.ClrType, expr.SqlType, name, null, expr, expr.SourceExpression) {
            System.Diagnostics.Debug.Assert(expr != null); 
        }

        internal SqlAlias Alias {
            get { return this.alias; } 
            set { this.alias = value; }
        } 
 
        internal string Name {
            get { return this.name; } 
            set { this.name = value; }
        }

        internal int Ordinal { 
            get { return this.ordinal; }
            set { this.ordinal = value; } 
        } 

        internal MetaDataMember MetaMember { 
            get { return this.member; }
        }

        ///  
        /// Set the column's Expression. This can change the type of the column.
        ///  
        internal SqlExpression Expression { 
            get {
                return this.expression; 
            }
            set {
                if (value != null) {
                    if (!this.ClrType.IsAssignableFrom(value.ClrType)) 
                        throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                    SqlColumnRef cref = value as SqlColumnRef; 
                    if (cref != null && cref.Column == this) 
                        throw Error.ColumnCannotReferToItself();
                } 
                this.expression = value;
            }
        }
 
        internal override ProviderType SqlType {
            get { 
                if (this.expression != null) 
                    return this.expression.SqlType;
                return this.sqlType; 
            }
        }
    }
 
    internal class SqlColumnRef : SqlExpression {
        private SqlColumn column; 
        internal SqlColumnRef(SqlColumn col) 
            : base(SqlNodeType.ColumnRef, col.ClrType, col.SourceExpression) {
            this.column = col; 
        }

        internal SqlColumn Column {
            get { return this.column; } 
        }
 
        internal override ProviderType SqlType { 
            get { return this.column.SqlType; }
        } 

        public override bool Equals(object obj) {
            SqlColumnRef cref = obj as SqlColumnRef;
            return cref != null && cref.Column == this.column; 
        }
 
        public override int GetHashCode() { 
            return this.column.GetHashCode();
        } 

        internal SqlColumn GetRootColumn() {
            SqlColumn c = this.column;
            while (c.Expression != null && c.Expression.NodeType == SqlNodeType.ColumnRef) { 
                c = ((SqlColumnRef)c.Expression).Column;
            } 
            return c; 
        }
    } 

    internal class SqlRow : SqlNode {
        private List columns;
 
        internal SqlRow(Expression sourceExpression)
            : base(SqlNodeType.Row, sourceExpression) { 
            this.columns = new List(); 
        }
 
        internal List Columns {
            get { return this.columns; }
        }
 
        internal SqlColumn Find(string name) {
            foreach (SqlColumn c in this.columns) { 
                if (name == c.Name) 
                    return c;
            } 
            return null;
        }
    }
 
    internal class SqlMemberAssign : SqlNode {
        private MemberInfo member; 
        private SqlExpression expression; 

        internal SqlMemberAssign(MemberInfo member, SqlExpression expr) 
            : base(SqlNodeType.MemberAssign, expr.SourceExpression) {
            if (member == null)
                throw Error.ArgumentNull("member");
            this.member = member; 
            this.Expression = expr;
        } 
 
        internal MemberInfo Member {
            get { return this.member; } 
        }

        internal SqlExpression Expression {
            get { return this.expression; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.expression = value;
            } 
        }
    }

    internal class SqlGrouping : SqlSimpleTypeExpression { 
        private SqlExpression key;
        private SqlExpression group; 
 
        internal SqlGrouping(Type clrType, ProviderType sqlType, SqlExpression key, SqlExpression group, Expression sourceExpression)
            : base(SqlNodeType.Grouping, clrType, sqlType, sourceExpression) { 
            if (key == null) throw Error.ArgumentNull("key");
            if (group == null) throw Error.ArgumentNull("group");
            this.key = key;
            this.group = group; 
        }
 
        internal SqlExpression Key { 
            get { return this.key; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (!this.key.ClrType.IsAssignableFrom(value.ClrType)
                    && !value.ClrType.IsAssignableFrom(this.key.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.key.ClrType, value.ClrType);
                this.key = value; 
            } 
        }
 
        internal SqlExpression Group {
            get { return this.group; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (value.ClrType != this.group.ClrType) 
                    throw Error.ArgumentWrongType("value", this.group.ClrType, value.ClrType); 
                this.group = value;
            } 
        }
    }

    internal class SqlNew : SqlSimpleTypeExpression { 
        private MetaType metaType;
        private ConstructorInfo constructor; 
        private List args; 
        private List argMembers;
        private List members; 

        internal SqlNew(MetaType metaType, ProviderType sqlType, ConstructorInfo cons, IEnumerable args, IEnumerable argMembers, IEnumerable members, Expression sourceExpression)
            : base(SqlNodeType.New, metaType.Type, sqlType, sourceExpression) {
            this.metaType = metaType; 

            if (cons == null && metaType.Type.IsClass) { // structs do not need to have a constructor 
                throw Error.ArgumentNull("cons"); 
            }
            this.constructor = cons; 
            this.args = new List();
            this.argMembers = new List();
            this.members = new List();
            if (args != null) { 
                this.args.AddRange(args);
            } 
            if (argMembers != null) { 
                this.argMembers.AddRange(argMembers);
            } 
            if (members != null) {
                this.members.AddRange(members);
            }
        } 

        internal MetaType MetaType { 
            get { return this.metaType; } 
        }
 
        internal ConstructorInfo Constructor {
            get { return this.constructor; }
        }
 
        internal List Args {
            get { return this.args; } 
        } 

        internal List ArgMembers { 
            get { return this.argMembers; }
        }

        internal List Members { 
            get { return this.members; }
        } 
 
        internal SqlExpression Find(MemberInfo mi) {
            for (int i = 0, n = this.argMembers.Count; i < n; i++) { 
                MemberInfo argmi = this.argMembers[i];
                if (argmi.Name == mi.Name) {
                    return this.args[i];
                } 
            }
 
            foreach (SqlMemberAssign ma in this.Members) { 
                if (ma.Member.Name == mi.Name) {
                    return ma.Expression; 
                }
            }

            return null; 
        }
    } 
 
    internal class SqlMethodCall : SqlSimpleTypeExpression {
        private MethodInfo method; 
        private SqlExpression obj;
        private List arguments;

        internal SqlMethodCall(Type clrType, ProviderType sqlType, MethodInfo method, SqlExpression obj, IEnumerable args, Expression sourceExpression) 
            : base(SqlNodeType.MethodCall, clrType, sqlType, sourceExpression) {
            if (method == null) 
                throw Error.ArgumentNull("method"); 
            this.method = method;
            this.Object = obj; 
            this.arguments = new List();
            if (args != null)
                this.arguments.AddRange(args);
        } 

        internal MethodInfo Method { 
            get { return this.method; } 
        }
 
        internal SqlExpression Object {
            get { return this.obj; }
            set {
                if (value == null && !this.method.IsStatic) 
                    throw Error.ArgumentNull("value");
                if (value != null && !this.method.DeclaringType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.method.DeclaringType, value.ClrType); 
                this.obj = value;
            } 
        }

        internal List Arguments {
            get { return this.arguments; } 
        }
    } 
 
    internal class SqlIncludeScope : SqlNode {
        SqlNode child; 
        internal SqlIncludeScope(SqlNode child, Expression sourceExpression)
            : base(SqlNodeType.IncludeScope, sourceExpression) {
            this.child = child;
        } 
        internal SqlNode Child {
            get {return this.child;} 
            set {this.child = value;} 
        }
    } 

    internal class SqlClientArray : SqlSimpleTypeExpression {
        private List expressions;
 
        internal SqlClientArray(Type clrType, ProviderType sqlType, SqlExpression[ ] exprs, Expression sourceExpression)
            : base(SqlNodeType.ClientArray, clrType, sqlType, sourceExpression) { 
            this.expressions = new List(); 
            if (exprs != null)
                this.Expressions.AddRange(exprs); 
        }

        internal List Expressions {
            get { return this.expressions; } 
        }
    } 
 
    internal class SqlLink : SqlSimpleTypeExpression {
        private MetaType rowType; 
        private SqlExpression expression;
        private MetaDataMember member;
        private List keyExpressions;
        private SqlExpression expansion; 
        private object id;
 
        internal SqlLink(object id, MetaType rowType, Type clrType, ProviderType sqlType, SqlExpression expression, MetaDataMember member, IEnumerable keyExpressions, SqlExpression expansion, Expression sourceExpression) 
            : base(SqlNodeType.Link, clrType, sqlType, sourceExpression) {
            this.id = id; 
            this.rowType = rowType;
            this.expansion = expansion;
            this.expression = expression;
            this.member = member; 
            this.keyExpressions = new List();
            if (keyExpressions != null) 
                this.keyExpressions.AddRange(keyExpressions); 
        }
 
        internal MetaType RowType {
            get { return this.rowType; }
        }
 
        internal SqlExpression Expansion {
            get { return this.expansion; } 
            set { this.expansion = value; } 
        }
 

        internal SqlExpression Expression {
            get { return this.expression; }
            set { this.expression = value; } 
        }
 
        internal MetaDataMember Member { 
            get { return this.member; }
        } 

        internal List KeyExpressions {
            get { return this.keyExpressions; }
        } 

        internal object Id { 
            get { return this.id; } 
        }
    } 

    internal class SqlExprSet : SqlExpression {
        private List expressions;
 
        internal SqlExprSet(Type clrType, IEnumerable  exprs, Expression sourceExpression)
            : base(SqlNodeType.ExprSet, clrType, sourceExpression) { 
            this.expressions = new List(exprs); 
        }
 
        internal List Expressions {
            get { return this.expressions; }
        }
 
        /// 
        /// Get the first non-set expression of the set by drilling 
        /// down the left expressions. 
        /// 
        internal SqlExpression GetFirstExpression() { 
            SqlExpression expr = expressions[0];
            while (expr is SqlExprSet) {
                expr = ((SqlExprSet)expr).Expressions[0];
            } 
            return expr;
        } 
 
        internal override ProviderType SqlType {
            get { return this.expressions[0].SqlType; } 
        }
    }

    internal class SqlSubSelect : SqlSimpleTypeExpression { 
        private SqlSelect select;
 
        internal SqlSubSelect(SqlNodeType nt , Type clrType, ProviderType sqlType , SqlSelect select) 
            : base(nt, clrType, sqlType, select.SourceExpression) {
            switch (nt) { 
                case SqlNodeType.Multiset:
                case SqlNodeType.ScalarSubSelect:
                case SqlNodeType.Element:
                case SqlNodeType.Exists: 
                    break;
                default: 
                    throw Error.UnexpectedNode(nt); 
            }
            this.Select = select; 
        }

        internal SqlSelect Select {
            get { return this.select; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value"); 
                this.select = value;
            } 
        }
    }

    internal class SqlClientQuery : SqlSimpleTypeExpression { 
        private SqlSubSelect query;
        private List arguments; 
        private List parameters; 
        int ordinal;
 
        internal SqlClientQuery(SqlSubSelect subquery)
            : base(SqlNodeType.ClientQuery, subquery.ClrType, subquery.SqlType, subquery.SourceExpression) {
            this.query = subquery;
            this.arguments = new List(); 
            this.parameters = new List();
        } 
 
        internal SqlSubSelect Query {
            get { return this.query; } 
            set {
                if (value == null || (this.query != null && this.query.ClrType != value.ClrType))
                    throw Error.ArgumentWrongType(value, this.query.ClrType, value.ClrType);
                this.query = value; 
            }
        } 
 
        internal List Arguments {
            get { return this.arguments; } 
        }

        internal List Parameters {
            get { return this.parameters; } 
        }
 
        internal int Ordinal { 
            get { return this.ordinal; }
            set { this.ordinal = value; } 
        }
    }

    internal class SqlJoinedCollection : SqlSimpleTypeExpression { 
        private SqlExpression expression;
        private SqlExpression count; 
 
        internal SqlJoinedCollection(Type clrType, ProviderType sqlType, SqlExpression expression, SqlExpression count, Expression sourceExpression)
            : base(SqlNodeType.JoinedCollection, clrType, sqlType, sourceExpression) { 
            this.expression = expression;
            this.count = count;
        }
 
        internal SqlExpression Expression {
            get { return this.expression; } 
            set { 
                if (value == null || this.expression != null && this.expression.ClrType != value.ClrType)
                    throw Error.ArgumentWrongType(value, this.expression.ClrType, value.ClrType); 
                this.expression = value;
            }
        }
 
        internal SqlExpression Count {
            get { return this.count; } 
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                if (value.ClrType != typeof(int))
                    throw Error.ArgumentWrongType(value, typeof(int), value.ClrType);
                this.count = value;
            } 
        }
    } 
 
    internal class SqlUpdate : SqlStatement {
        private SqlSelect select; 
        private List assignments;

        internal SqlUpdate(SqlSelect select, IEnumerable assignments, Expression sourceExpression)
            : base(SqlNodeType.Update, sourceExpression) { 
            this.Select = select;
            this.assignments = new List(assignments); 
        } 

        internal SqlSelect Select { 
            get { return this.select; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.select = value;
            } 
        } 

        internal List Assignments { 
            get { return this.assignments; }
        }
    }
 
    internal class SqlInsert : SqlStatement {
        private SqlTable table; 
        private SqlRow row; 
        private SqlExpression expression;
        private SqlColumn outputKey; 
        private bool outputToLocal;

        internal SqlInsert(SqlTable table, SqlExpression expr, Expression sourceExpression)
            : base(SqlNodeType.Insert, sourceExpression) { 
            this.Table = table;
            this.Expression = expr; 
            this.Row = new SqlRow(sourceExpression); 
        }
 
        internal SqlTable Table {
            get { return this.table; }
            set {
                if (value == null) 
                    throw Error.ArgumentNull("null");
                this.table = value; 
            } 
        }
 
        internal SqlRow Row {
            get { return this.row; }
            set { this.row = value; }
        } 

        internal SqlExpression Expression { 
            get { return this.expression; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("null");
                if (!this.table.RowType.Type.IsAssignableFrom(value.ClrType))
                    throw Error.ArgumentWrongType("value", this.table.RowType, value.ClrType);
                this.expression = value; 
            }
        } 
 
        internal SqlColumn OutputKey {
            get { return this.outputKey; } 
            set { this.outputKey = value; }
        }

        internal bool OutputToLocal { 
            get { return this.outputToLocal; }
            set { this.outputToLocal = value; } 
        } 
    }
 
    internal class SqlDelete : SqlStatement {
        private SqlSelect select;

        internal SqlDelete(SqlSelect select, Expression sourceExpression) 
            : base(SqlNodeType.Delete, sourceExpression) {
            this.Select = select; 
        } 

        internal SqlSelect Select { 
            get { return this.select; }
            set {
                if (value == null)
                    throw Error.ArgumentNull("value"); 
                this.select = value;
            } 
        } 
    }
 
    internal class SqlBlock : SqlStatement {
        private List statements;

        internal SqlBlock(Expression sourceExpression) 
            : base(SqlNodeType.Block, sourceExpression) {
            this.statements = new List(); 
        } 

        internal List Statements { 
            get { return this.statements; }
        }
    }
 
    internal class SqlAssign : SqlStatement {
        private SqlExpression leftValue; 
        private SqlExpression rightValue; 

        internal SqlAssign(SqlExpression lValue, SqlExpression rValue, Expression sourceExpression) 
            : base(SqlNodeType.Assign, sourceExpression) {
            this.LValue = lValue;
            this.RValue = rValue;
        } 

        internal SqlExpression LValue { 
            get { return this.leftValue; } 
            set {
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (this.rightValue != null && !value.ClrType.IsAssignableFrom(this.rightValue.ClrType))
                    throw Error.ArgumentWrongType("value", this.rightValue.ClrType, value.ClrType);
                this.leftValue = value; 
            }
        } 
 
        internal SqlExpression RValue {
            get { return this.rightValue; } 
            set {
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (this.leftValue != null && !this.leftValue.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.leftValue.ClrType, value.ClrType);
                this.rightValue = value; 
            } 
        }
    } 

    internal class SqlDoNotVisitExpression : SqlExpression {
        private SqlExpression expression;
 
        internal SqlDoNotVisitExpression(SqlExpression expr)
            : base(SqlNodeType.DoNotVisit, expr.ClrType, expr.SourceExpression) { 
            if (expr == null) 
                throw Error.ArgumentNull("expr");
            this.expression = expr; 
        }

        internal SqlExpression Expression {
            get { return this.expression; } 
        }
 
        internal override ProviderType SqlType { 
            get { return this.expression.SqlType; }
        } 
    }

    internal class SqlOptionalValue : SqlSimpleTypeExpression {
        private SqlExpression hasValue; 
        private SqlExpression expressionValue;
 
        internal SqlOptionalValue( SqlExpression hasValue, SqlExpression value) 
            : base(SqlNodeType.OptionalValue, value.ClrType, value.SqlType, value.SourceExpression) {
            this.HasValue = hasValue; 
            this.Value = value;
        }

        internal SqlExpression HasValue { 
            get { return this.hasValue; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                this.hasValue = value; 
            }
        }

        internal SqlExpression Value { 
            get { return this.expressionValue; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (value.ClrType != this.ClrType) 
                    throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                this.expressionValue = value;
            }
        } 
    }
 
    internal class SqlFunctionCall : SqlSimpleTypeExpression { 
        private string name;
        private List arguments; 

        internal SqlFunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable  args , Expression source)
            : this(SqlNodeType.FunctionCall, clrType , sqlType, name, args, source) {
        } 

        internal SqlFunctionCall(SqlNodeType nodeType, Type clrType, ProviderType sqlType, string name , IEnumerable  args , Expression source) 
            : base(nodeType, clrType, sqlType, source) { 
            this.name = name;
            this.arguments = new List(args); 
        }

        internal string Name {
            get { return this.name; } 
        }
 
        internal List Arguments { 
            get { return this.arguments; }
        } 
    }

    /// 
    /// This class is used to represent a table value function.  It inherits normal function 
    /// call functionality, and adds TVF specific members.
    ///  
    internal class SqlTableValuedFunctionCall : SqlFunctionCall { 
        private MetaType rowType;
        private List columns; 

        internal SqlTableValuedFunctionCall(MetaType rowType, Type clrType, ProviderType sqlType, string name, IEnumerable  args , Expression source)
            : base(SqlNodeType.TableValuedFunctionCall, clrType , sqlType, name, args, source) {
            this.rowType = rowType; 
            this.columns = new List();
        } 
 
        internal MetaType RowType {
            get { return this.rowType; } 
        }

        internal List Columns {
            get { return this.columns; } 
        }
 
        internal SqlColumn Find(string name) { 
            foreach (SqlColumn c in this.Columns) {
                if (c.Name == name) 
                    return c;
            }
            return null;
        } 

    } 
 
    internal class SqlSharedExpression : SqlExpression {
        private SqlExpression expr; 

        internal SqlSharedExpression(SqlExpression expr)
          : base(SqlNodeType.SharedExpression, expr.ClrType, expr.SourceExpression) {
            this.expr = expr; 
        }
 
        internal SqlExpression Expression { 
            get { return this.expr; }
            set { 
                if (value == null)
                    throw Error.ArgumentNull("value");
                if (!this.ClrType.IsAssignableFrom(value.ClrType)
                    && !value.ClrType.IsAssignableFrom(this.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                this.expr = value; 
            } 
        }
 
        internal override ProviderType SqlType {
            get { return this.expr.SqlType; }
        }
    } 

    internal class SqlSharedExpressionRef : SqlExpression { 
        private SqlSharedExpression expr; 

        internal SqlSharedExpressionRef(SqlSharedExpression expr) 
            : base(SqlNodeType.SharedExpressionRef, expr.ClrType, expr.SourceExpression) {
            this.expr = expr;
        }
 
        internal SqlSharedExpression SharedExpression {
            get { return this.expr; } 
        } 

        internal override ProviderType SqlType { 
            get { return this.expr.SqlType; }
        }
    }
 
    internal class SqlSimpleExpression : SqlExpression {
        private SqlExpression expr; 
 
        internal SqlSimpleExpression(SqlExpression expr)
            : base(SqlNodeType.SimpleExpression, expr.ClrType, expr.SourceExpression) { 
            this.expr = expr;
        }

        internal SqlExpression Expression { 
            get { return this.expr; }
            set { 
                if (value == null) 
                    throw Error.ArgumentNull("value");
                if (!this.ClrType.IsAssignableFrom(value.ClrType)) 
                    throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
                this.expr = value;
            }
        } 

        internal override ProviderType SqlType { 
            get { return this.expr.SqlType; } 
        }
    } 

    internal class SqlClientParameter : SqlSimpleTypeExpression {
        // Expression>
        LambdaExpression accessor; 
        internal SqlClientParameter(Type clrType, ProviderType sqlType, LambdaExpression accessor, Expression sourceExpression):
            base(SqlNodeType.ClientParameter, clrType, sqlType, sourceExpression) { 
            this.accessor = accessor; 
        }
        internal LambdaExpression Accessor { 
            get { return this.accessor; }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

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