1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using System.Text;
5 using System.Linq.Expressions;
6 using System.Diagnostics;
7 using System.Data;
8 
9 namespace System.Data.Linq.SqlClient {
10     using System.Data.Linq.Mapping;
11     using System.Data.Linq.Provider;
12     using System.Diagnostics.CodeAnalysis;
13 
14     internal enum SqlNodeType {
15         Add,
16         Alias,
17         AliasRef,
18         And,
19         Assign,
20         Avg,
21         Between,
22         BitAnd,
23         BitNot,
24         BitOr,
25         BitXor,
26         Block,
27         ClientArray,
28         ClientCase,
29         ClientParameter,
30         ClientQuery,
31         ClrLength,
32         Coalesce,
33         Column,
34         ColumnRef,
35         Concat,
36         Convert,
37         Count,
38         Delete,
39         DiscriminatedType,
40         DiscriminatorOf,
41         Div,
42         DoNotVisit,
43         Element,
44         ExprSet,
45         EQ,
46         EQ2V,
47         Exists,
48         FunctionCall,
49         In,
50         IncludeScope,
51         IsNotNull,
52         IsNull,
53         LE,
54         Lift,
55         Link,
56         Like,
57         LongCount,
58         LT,
59         GE,
60         Grouping,
61         GT,
62         Insert,
63         Join,
64         JoinedCollection,
65         Max,
66         MethodCall,
67         Member,
68         MemberAssign,
69         Min,
70         Mod,
71         Mul,
72         Multiset,
73         NE,
74         NE2V,
75         Negate,
76         New,
77         Not,
78         Not2V,
79         Nop,
80         Or,
81         OptionalValue,
82         OuterJoinedValue,
83         Parameter,
84         Property,
85         Row,
86         RowNumber,
87         ScalarSubSelect,
88         SearchedCase,
89         Select,
90         SharedExpression,
91         SharedExpressionRef,
92         SimpleCase,
93         SimpleExpression,
94         Stddev,
95         StoredProcedureCall,
96         Sub,
97         Sum,
98         Table,
99         TableValuedFunctionCall,
100         Treat,
101         TypeCase,
102         Union,
103         Update,
104         UserColumn,
105         UserQuery,
106         UserRow,
107         Variable,
108         Value,
109         ValueOf
110     }
111 
112     [System.Diagnostics.DebuggerDisplay("text = {Text}, \r\nsource = {SourceExpression}")]
113     internal abstract class SqlNode {
114         private SqlNodeType nodeType;
115         private Expression sourceExpression;
116 
SqlNode(SqlNodeType nodeType, Expression sourceExpression)117         internal SqlNode(SqlNodeType nodeType, Expression sourceExpression) {
118             this.nodeType = nodeType;
119             this.sourceExpression = sourceExpression;
120         }
121 
122         internal Expression SourceExpression {
123             get { return this.sourceExpression; }
124         }
125 
ClearSourceExpression()126         internal void ClearSourceExpression() {
127             this.sourceExpression = null;
128         }
129 
130         internal SqlNodeType NodeType {
131             get { return this.nodeType; }
132         }
133 
134 #if DEBUG
135         private static DbFormatter formatter;
136         internal static DbFormatter Formatter {
137             get { return formatter; }
138             set { formatter = value; }
139         }
140 
141         internal string Text {
142             get {
143                 if (Formatter == null)
144                     return "SqlNode.Formatter is not assigned";
145                 return SqlNode.Formatter.Format(this, true);
146             }
147         }
148 #endif
149     }
150 
151     internal abstract class SqlExpression : SqlNode {
152         private Type clrType;
SqlExpression(SqlNodeType nodeType, Type clrType, Expression sourceExpression)153         internal SqlExpression(SqlNodeType nodeType, Type clrType, Expression sourceExpression)
154             : base(nodeType, sourceExpression) {
155             this.clrType = clrType;
156         }
157 
158         internal Type ClrType {
159             get { return this.clrType; }
160         }
161 
162         // note: changing the CLR type of a node is potentially dangerous
SetClrType(Type type)163         internal void SetClrType(Type type) {
164             this.clrType = type;
165         }
166 
167         internal abstract ProviderType SqlType { get; }
168 
169         /// <summary>
170         /// Drill down looking for a constant root expression, returning true if found.
171         /// </summary>
172         internal bool IsConstantColumn {
173             get {
174                 if (this.NodeType == SqlNodeType.Column) {
175                     SqlColumn col = (SqlColumn)this;
176                     if (col.Expression != null) {
177                         return col.Expression.IsConstantColumn;
178                     }
179                 }
180                 else if (this.NodeType == SqlNodeType.ColumnRef) {
181                     return ((SqlColumnRef)this).Column.IsConstantColumn;
182                 }
183                 else if (this.NodeType == SqlNodeType.OptionalValue) {
184                     return ((SqlOptionalValue)this).Value.IsConstantColumn;
185                 }
186                 else if (this.NodeType == SqlNodeType.Value ||
187                         this.NodeType == SqlNodeType.Parameter) {
188                     return true;
189                 }
190                 return false;
191             }
192         }
193     }
194 
195     /// <summary>
196     /// A SqlExpression with a simple implementation of ClrType and SqlType.
197     /// </summary>
198     internal abstract class SqlSimpleTypeExpression : SqlExpression {
199         private ProviderType sqlType;
200 
SqlSimpleTypeExpression(SqlNodeType nodeType, Type clrType, ProviderType sqlType, Expression sourceExpression)201         internal SqlSimpleTypeExpression(SqlNodeType nodeType, Type clrType, ProviderType sqlType, Expression sourceExpression)
202             : base(nodeType, clrType, sourceExpression) {
203             this.sqlType = sqlType;
204         }
205 
206         internal override ProviderType SqlType {
207             get { return this.sqlType; }
208         }
209 
SetSqlType(ProviderType type)210         internal void SetSqlType(ProviderType type) {
211             this.sqlType = type;
212         }
213     }
214 
215     internal class SqlDiscriminatorOf : SqlSimpleTypeExpression {
216         SqlExpression obj;
SqlDiscriminatorOf(SqlExpression obj, Type clrType, ProviderType sqlType, Expression sourceExpression)217         internal SqlDiscriminatorOf(SqlExpression obj, Type clrType, ProviderType sqlType, Expression sourceExpression)
218             : base(SqlNodeType.DiscriminatorOf, clrType, sqlType, sourceExpression) {
219             this.obj = obj;
220         }
221         internal SqlExpression Object {
222             get { return this.obj; }
223             set { this.obj = value; }
224         }
225     }
226 
227 
228     /// <summary>
229     /// Represents a dynamic CLR type that is chosen based on a discriminator expression.
230     /// </summary>
231     internal class SqlDiscriminatedType : SqlExpression {
232         private ProviderType sqlType;
233         private SqlExpression discriminator;
234         private MetaType targetType;
SqlDiscriminatedType(ProviderType sqlType, SqlExpression discriminator, MetaType targetType, Expression sourceExpression)235         internal SqlDiscriminatedType(ProviderType sqlType, SqlExpression discriminator, MetaType targetType, Expression sourceExpression)
236             : base(SqlNodeType.DiscriminatedType,
237                    typeof(Type),
238                    sourceExpression) {
239             if (discriminator == null)
240                 throw Error.ArgumentNull("discriminator");
241             this.discriminator = discriminator;
242             this.targetType = targetType;
243             this.sqlType = sqlType;
244         }
245         internal override ProviderType SqlType {
246             get { return this.sqlType; }
247         }
248         internal SqlExpression Discriminator {
249             get { return this.discriminator; }
250             set { this.discriminator = value; }
251         }
252 
253         internal MetaType TargetType {
254             get { return this.targetType; }
255         }
256     }
257 
258     internal abstract class SqlStatement : SqlNode {
SqlStatement(SqlNodeType nodeType, Expression sourceExpression)259         internal SqlStatement(SqlNodeType nodeType, Expression sourceExpression)
260             : base(nodeType, sourceExpression) {
261         }
262     }
263 
264     internal abstract class SqlSource : SqlNode {
SqlSource(SqlNodeType nt, Expression sourceExpression)265         internal SqlSource(SqlNodeType nt, Expression sourceExpression)
266             : base(nt, sourceExpression) {
267         }
268     }
269 
270     internal class SqlSelect : SqlStatement {
271         private SqlExpression top;
272         private bool isPercent;
273         private bool isDistinct;
274         private SqlExpression selection;
275         private SqlRow row;
276         private SqlSource from;
277         private SqlExpression where;
278         private List<SqlExpression> groupBy;
279         private SqlExpression having;
280         private List<SqlOrderExpression> orderBy;
281         private SqlOrderingType orderingType;
282         private bool squelch;
283 
SqlSelect(SqlExpression selection, SqlSource from, Expression sourceExpression)284         internal SqlSelect(SqlExpression selection, SqlSource from, Expression sourceExpression)
285             : base(SqlNodeType.Select, sourceExpression) {
286             this.Row = new SqlRow(sourceExpression);
287             this.Selection = selection;
288             this.From = from;
289             this.groupBy = new List<SqlExpression>();
290             this.orderBy = new List<SqlOrderExpression>();
291             this.orderingType = SqlOrderingType.Default;
292         }
293 
294         internal SqlExpression Top {
295             get { return this.top; }
296             set { this.top = value; }
297         }
298 
299         internal bool IsPercent {
300             get { return this.isPercent; }
301             set { this.isPercent = value; }
302         }
303 
304         internal bool IsDistinct {
305             get { return this.isDistinct; }
306             set { this.isDistinct = value; }
307         }
308 
309         internal SqlExpression Selection {
310             get { return this.selection; }
311             set {
312                 if (value == null)
313                     throw Error.ArgumentNull("value");
314                 this.selection = value;
315             }
316         }
317 
318         internal SqlRow Row {
319             get { return this.row; }
320             set {
321                 if (value == null)
322                     throw Error.ArgumentNull("value");
323                 this.row = value;
324             }
325         }
326 
327         internal SqlSource From {
328             get { return this.from; }
329             set { this.from = value; }
330         }
331 
332         internal SqlExpression Where {
333             get { return this.where; }
334             set {
335                 if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) {
336                     throw Error.ArgumentWrongType("value", "bool", value.ClrType);
337                 }
338                 this.where = value;
339             }
340         }
341 
342         internal List<SqlExpression> GroupBy {
343             get { return this.groupBy; }
344         }
345 
346         internal SqlExpression Having {
347             get { return this.having; }
348             set {
349                 if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) {
350                     throw Error.ArgumentWrongType("value", "bool", value.ClrType);
351                 }
352                 this.having = value;
353             }
354         }
355 
356         internal List<SqlOrderExpression> OrderBy {
357             get { return this.orderBy; }
358         }
359 
360         internal SqlOrderingType OrderingType {
361             get { return this.orderingType; }
362             set { this.orderingType = value; }
363         }
364 
365         internal bool DoNotOutput {
366             get { return this.squelch; }
367             set { this.squelch = value; }
368         }
369     }
370 
371     internal enum SqlOrderingType {
372         Default,
373         Never,
374         Blocked,
375         Always
376     }
377 
378     internal class SqlTable : SqlNode {
379         private MetaTable table;
380         private MetaType rowType;
381         private ProviderType sqlRowType;
382         private List<SqlColumn> columns;
383 
SqlTable(MetaTable table, MetaType rowType, ProviderType sqlRowType, Expression sourceExpression)384         internal SqlTable(MetaTable table, MetaType rowType, ProviderType sqlRowType, Expression sourceExpression)
385             : base(SqlNodeType.Table, sourceExpression) {
386             this.table = table;
387             this.rowType = rowType;
388             this.sqlRowType = sqlRowType;
389             this.columns = new List<SqlColumn>();
390         }
391 
392         internal MetaTable MetaTable {
393             get { return this.table; }
394         }
395 
396         internal string Name {
397             get { return this.table.TableName; }
398         }
399 
400         internal List<SqlColumn> Columns {
401             get { return this.columns; }
402         }
403 
404         internal MetaType RowType {
405             get { return this.rowType; }
406         }
407 
408         internal ProviderType SqlRowType {
409             get { return this.sqlRowType; }
410         }
411 
Find(string columnName)412         internal SqlColumn Find(string columnName) {
413             foreach (SqlColumn c in this.Columns) {
414                 if (c.Name == columnName)
415                     return c;
416             }
417             return null;
418         }
419 
420     }
421 
422     internal class SqlUserQuery : SqlNode {
423         private string queryText;
424         private SqlExpression projection;
425         private List<SqlExpression> args;
426         private List<SqlUserColumn> columns;
427 
SqlUserQuery(SqlNodeType nt, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)428         internal SqlUserQuery(SqlNodeType nt, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)
429             : base(nt, source) {
430             this.Projection = projection;
431             this.args = (args != null) ? new List<SqlExpression>(args) : new List<SqlExpression>();
432             this.columns = new List<SqlUserColumn>();
433         }
434 
SqlUserQuery(string queryText, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)435         internal SqlUserQuery(string queryText, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)
436             : base(SqlNodeType.UserQuery, source) {
437             this.queryText = queryText;
438             this.Projection = projection;
439             this.args = (args != null) ? new List<SqlExpression>(args) : new List<SqlExpression>();
440             this.columns = new List<SqlUserColumn>();
441         }
442 
443         internal string QueryText {
444             get { return this.queryText; }
445         }
446 
447         internal SqlExpression Projection {
448             get { return this.projection; }
449             set {
450                 if (this.projection != null && this.projection.ClrType != value.ClrType)
451                     throw Error.ArgumentWrongType("value", this.projection.ClrType, value.ClrType);
452                 this.projection = value;
453             }
454         }
455 
456         internal List<SqlExpression> Arguments {
457             get { return this.args; }
458         }
459 
460         internal List<SqlUserColumn> Columns {
461             get { return this.columns; }
462         }
463 
Find(string name)464         internal SqlUserColumn Find(string name) {
465             foreach (SqlUserColumn c in this.Columns) {
466                 if (c.Name == name)
467                     return c;
468             }
469             return null;
470         }
471     }
472 
473     internal class SqlStoredProcedureCall : SqlUserQuery {
474         private MetaFunction function;
475 
SqlStoredProcedureCall(MetaFunction function, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)476         internal SqlStoredProcedureCall(MetaFunction function, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)
477             : base(SqlNodeType.StoredProcedureCall, projection, args, source) {
478             if (function == null)
479                 throw Error.ArgumentNull("function");
480             this.function = function;
481         }
482 
483         internal MetaFunction Function {
484             get { return this.function; }
485         }
486     }
487 
488     internal class SqlUserRow : SqlSimpleTypeExpression {
489         private SqlUserQuery query;
490         private MetaType rowType;
491 
SqlUserRow(MetaType rowType, ProviderType sqlType, SqlUserQuery query, Expression source)492         internal SqlUserRow(MetaType rowType, ProviderType sqlType, SqlUserQuery query, Expression source)
493             : base(SqlNodeType.UserRow, rowType.Type, sqlType, source) {
494             this.Query = query;
495             this.rowType = rowType;
496         }
497 
498         internal MetaType RowType {
499             get { return this.rowType; }
500         }
501 
502         internal SqlUserQuery Query {
503             get { return this.query; }
504             set {
505                 if (value == null)
506                     throw Error.ArgumentNull("value");
507                 if (value.Projection != null && value.Projection.ClrType != this.ClrType)
508                     throw Error.ArgumentWrongType("value", this.ClrType, value.Projection.ClrType);
509                 this.query = value;
510             }
511         }
512     }
513 
514     internal class SqlUserColumn : SqlSimpleTypeExpression {
515         private SqlUserQuery query;
516         private string name;
517         private bool isRequired;
518 
SqlUserColumn(Type clrType, ProviderType sqlType, SqlUserQuery query, string name, bool isRequired, Expression source)519         internal SqlUserColumn(Type clrType, ProviderType sqlType, SqlUserQuery query, string name, bool isRequired, Expression source)
520             : base(SqlNodeType.UserColumn, clrType, sqlType, source) {
521             this.Query = query;
522             this.name = name;
523             this.isRequired = isRequired;
524         }
525 
526         internal SqlUserQuery Query {
527             get { return this.query; }
528             set {
529                 if (value == null)
530                     throw Error.ArgumentNull("value");
531                 if (this.query != null && this.query != value)
532                     throw Error.ArgumentWrongValue("value");
533                 this.query = value;
534             }
535         }
536 
537         internal string Name {
538             get { return this.name; }
539         }
540 
541         internal bool IsRequired {
542             get { return this.isRequired; }
543         }
544     }
545 
546     internal class SqlAlias : SqlSource {
547         private string name;
548         private SqlNode node;
549 
SqlAlias(SqlNode node)550         internal SqlAlias(SqlNode node)
551             : base(SqlNodeType.Alias, node.SourceExpression) {
552             this.Node = node;
553         }
554 
555         internal string Name {
556             get { return this.name; }
557             set { this.name = value; }
558         }
559 
560         internal SqlNode Node {
561             get { return this.node; }
562             set {
563                 if (value == null)
564                     throw Error.ArgumentNull("value");
565                 if (!(value is SqlExpression || value is SqlSelect || value is SqlTable || value is SqlUnion))
566                     throw Error.UnexpectedNode(value.NodeType);
567                 this.node = value;
568             }
569         }
570     }
571 
572     internal class SqlAliasRef : SqlExpression {
573         private SqlAlias alias;
574 
SqlAliasRef(SqlAlias alias)575         internal SqlAliasRef(SqlAlias alias)
576             : base(SqlNodeType.AliasRef, GetClrType(alias.Node), alias.SourceExpression) {
577             if (alias == null)
578                 throw Error.ArgumentNull("alias");
579             this.alias = alias;
580         }
581 
582         internal SqlAlias Alias {
583             get { return this.alias; }
584         }
585 
586         internal override ProviderType SqlType {
587             get { return GetSqlType(this.alias.Node); }
588         }
589 
GetClrType(SqlNode node)590         private static Type GetClrType(SqlNode node) {
591             SqlTableValuedFunctionCall tvf = node as SqlTableValuedFunctionCall;
592             if (tvf != null)
593                 return tvf.RowType.Type;
594             SqlExpression exp = node as SqlExpression;
595             if (exp != null) {
596                 if (TypeSystem.IsSequenceType(exp.ClrType))
597                     return TypeSystem.GetElementType(exp.ClrType);
598                 return exp.ClrType;
599             }
600             SqlSelect sel = node as SqlSelect;
601             if (sel != null)
602                 return sel.Selection.ClrType;
603             SqlTable tab = node as SqlTable;
604             if (tab != null)
605                 return tab.RowType.Type;
606             SqlUnion su = node as SqlUnion;
607             if (su != null)
608                 return su.GetClrType();
609             throw Error.UnexpectedNode(node.NodeType);
610         }
611 
GetSqlType(SqlNode node)612         private static ProviderType GetSqlType(SqlNode node) {
613             SqlExpression exp = node as SqlExpression;
614             if (exp != null)
615                 return exp.SqlType;
616             SqlSelect sel = node as SqlSelect;
617             if (sel != null)
618                 return sel.Selection.SqlType;
619             SqlTable tab = node as SqlTable;
620             if (tab != null)
621                 return tab.SqlRowType;
622             SqlUnion su = node as SqlUnion;
623             if (su != null)
624                 return su.GetSqlType();
625             throw Error.UnexpectedNode(node.NodeType);
626         }
627     }
628 
629     internal class SqlJoin : SqlSource {
630         private SqlJoinType joinType;
631         private SqlSource left;
632         private SqlSource right;
633         private SqlExpression condition;
634 
SqlJoin(SqlJoinType type, SqlSource left, SqlSource right, SqlExpression cond, Expression sourceExpression)635         internal SqlJoin(SqlJoinType type, SqlSource left, SqlSource right, SqlExpression cond, Expression sourceExpression)
636             : base(SqlNodeType.Join, sourceExpression) {
637             this.JoinType = type;
638             this.Left = left;
639             this.Right = right;
640             this.Condition = cond;
641         }
642 
643         internal SqlJoinType JoinType {
644             get { return this.joinType; }
645             set { this.joinType = value; }
646         }
647 
648         internal SqlSource Left {
649             get { return this.left; }
650             set {
651                 if (value == null)
652                     throw Error.ArgumentNull("value");
653                 this.left = value;
654             }
655         }
656 
657         internal SqlSource Right {
658             get { return this.right; }
659             set {
660                 if (value == null)
661                     throw Error.ArgumentNull("value");
662                 this.right = value;
663             }
664         }
665 
666         internal SqlExpression Condition {
667             get { return this.condition; }
668             set { this.condition = value; }
669         }
670     }
671 
672     internal enum SqlJoinType {
673         Cross,
674         Inner,
675         LeftOuter,
676         CrossApply,
677         OuterApply
678     }
679 
680     internal class SqlUnion : SqlNode {
681         private SqlNode left;
682         private SqlNode right;
683         private bool all;
684 
SqlUnion(SqlNode left, SqlNode right, bool all)685         internal SqlUnion(SqlNode left, SqlNode right, bool all)
686             : base(SqlNodeType.Union, right.SourceExpression) {
687             this.Left = left;
688             this.Right = right;
689             this.All = all;
690         }
691 
692         internal SqlNode Left {
693             get { return this.left; }
694             set {
695                 Validate(value);
696                 this.left = value;
697             }
698         }
699 
700         internal SqlNode Right {
701             get { return this.right; }
702             set {
703                 Validate(value);
704                 this.right = value;
705             }
706         }
707 
708         internal bool All {
709             get { return this.all; }
710             set { this.all = value; }
711         }
712 
713         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
Validate(SqlNode node)714         private void Validate(SqlNode node) {
715             if (node == null)
716                 throw Error.ArgumentNull("node");
717             if (!(node is SqlExpression || node is SqlSelect || node is SqlUnion))
718                 throw Error.UnexpectedNode(node.NodeType);
719         }
720 
GetClrType()721         internal Type GetClrType() {
722             SqlExpression exp = this.Left as SqlExpression;
723             if (exp != null)
724                 return exp.ClrType;
725             SqlSelect sel = this.Left as SqlSelect;
726             if (sel != null)
727                 return sel.Selection.ClrType;
728             throw Error.CouldNotGetClrType();
729         }
730 
GetSqlType()731         internal ProviderType GetSqlType() {
732             SqlExpression exp = this.Left as SqlExpression;
733             if (exp != null)
734                 return exp.SqlType;
735             SqlSelect sel = this.Left as SqlSelect;
736             if (sel != null)
737                 return sel.Selection.SqlType;
738             throw Error.CouldNotGetSqlType();
739         }
740     }
741 
742     internal class SqlNop : SqlSimpleTypeExpression {
SqlNop(Type clrType, ProviderType sqlType, Expression sourceExpression)743         internal SqlNop(Type clrType, ProviderType sqlType, Expression sourceExpression)
744             : base(SqlNodeType.Nop, clrType, sqlType, sourceExpression) {
745         }
746     }
747 
748     internal class SqlLift : SqlExpression {
749         internal SqlExpression liftedExpression;
750 
SqlLift(Type type, SqlExpression liftedExpression, Expression sourceExpression)751         internal SqlLift(Type type, SqlExpression liftedExpression, Expression sourceExpression)
752             : base(SqlNodeType.Lift, type, sourceExpression) {
753             if (liftedExpression == null)
754                 throw Error.ArgumentNull("liftedExpression");
755             this.liftedExpression = liftedExpression;
756         }
757 
758         internal SqlExpression Expression {
759             get { return this.liftedExpression; }
760             set {
761                 if (value == null)
762                     throw Error.ArgumentNull("value");
763                 this.liftedExpression = value;
764             }
765         }
766 
767         internal override ProviderType SqlType {
768             get { return this.liftedExpression.SqlType; }
769         }
770     }
771 
772     internal enum SqlOrderType {
773         Ascending,
774         Descending
775     }
776 
777     internal class SqlOrderExpression : IEquatable<SqlOrderExpression> {
778         private SqlOrderType orderType;
779         private SqlExpression expression;
780 
SqlOrderExpression(SqlOrderType type, SqlExpression expr)781         internal SqlOrderExpression(SqlOrderType type, SqlExpression expr) {
782             this.OrderType = type;
783             this.Expression = expr;
784         }
785 
786         internal SqlOrderType OrderType {
787             get { return this.orderType; }
788             set { this.orderType = value; }
789         }
790 
791         internal SqlExpression Expression {
792             get { return this.expression; }
793             set {
794                 if (value == null)
795                     throw Error.ArgumentNull("value");
796                 if (this.expression != null && !this.expression.ClrType.IsAssignableFrom(value.ClrType))
797                     throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
798                 this.expression = value;
799             }
800         }
801 
Equals(object obj)802         public override bool Equals(object obj) {
803             if (this.EqualsTo(obj as SqlOrderExpression))
804                 return true;
805 
806             return base.Equals(obj);
807         }
808 
Equals(SqlOrderExpression other)809         public bool Equals(SqlOrderExpression other) {
810             if (this.EqualsTo(other))
811                 return true;
812 
813             return base.Equals(other);
814         }
815 
EqualsTo(SqlOrderExpression other)816         private bool EqualsTo(SqlOrderExpression other) {
817             if (other == null)
818                 return false;
819             if (object.ReferenceEquals(this, other))
820                 return true;
821             if (this.OrderType != other.OrderType)
822                 return false;
823             if (!this.Expression.SqlType.Equals(other.Expression.SqlType))
824                 return false;
825 
826             SqlColumn col1 = SqlOrderExpression.UnwrapColumn(this.Expression);
827             SqlColumn col2 = SqlOrderExpression.UnwrapColumn(other.Expression);
828 
829             if (col1 == null || col2 == null)
830                 return false;
831 
832             return col1 == col2;
833         }
834 
GetHashCode()835         public override int GetHashCode() {
836             SqlColumn col = SqlOrderExpression.UnwrapColumn(this.Expression);
837             if (col != null)
838                 return col.GetHashCode();
839 
840             return base.GetHashCode();
841         }
842 
UnwrapColumn(SqlExpression expr)843         private static SqlColumn UnwrapColumn(SqlExpression expr) {
844             System.Diagnostics.Debug.Assert(expr != null);
845 
846             SqlUnary exprAsUnary = expr as SqlUnary;
847             if (exprAsUnary != null) {
848                 expr = exprAsUnary.Operand;
849             }
850 
851             SqlColumn exprAsColumn = expr as SqlColumn;
852             if (exprAsColumn != null) {
853                 return exprAsColumn;
854             }
855 
856             SqlColumnRef exprAsColumnRef = expr as SqlColumnRef;
857             if (exprAsColumnRef != null) {
858                 return exprAsColumnRef.GetRootColumn();
859             }
860             //
861             // For all other types return null to revert to default behavior for Equals()
862             // and GetHashCode()
863             //
864             return null;
865         }
866     }
867 
868     internal class SqlRowNumber : SqlSimpleTypeExpression {
869         private List<SqlOrderExpression> orderBy;
870 
871         internal List<SqlOrderExpression> OrderBy {
872             get { return orderBy; }
873         }
874 
SqlRowNumber(Type clrType, ProviderType sqlType, List<SqlOrderExpression> orderByList, Expression sourceExpression)875         internal SqlRowNumber(Type clrType, ProviderType sqlType, List<SqlOrderExpression> orderByList, Expression sourceExpression)
876             : base(SqlNodeType.RowNumber, clrType, sqlType, sourceExpression) {
877             if (orderByList == null) {
878                 throw Error.ArgumentNull("orderByList");
879             }
880 
881             this.orderBy = orderByList;
882         }
883     }
884 
885     internal class SqlUnary : SqlSimpleTypeExpression {
886         private SqlExpression operand;
887         private MethodInfo method;
888 
889         [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.")]
SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, Expression sourceExpression)890         internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, Expression sourceExpression)
891             : this(nt, clrType, sqlType, expr, null, sourceExpression) {
892         }
893 
SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, MethodInfo method, Expression sourceExpression)894         internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, MethodInfo method, Expression sourceExpression)
895             : base(nt, clrType, sqlType, sourceExpression) {
896             switch (nt) {
897                 case SqlNodeType.Not:
898                 case SqlNodeType.Not2V:
899                 case SqlNodeType.Negate:
900                 case SqlNodeType.BitNot:
901                 case SqlNodeType.IsNull:
902                 case SqlNodeType.IsNotNull:
903                 case SqlNodeType.Count:
904                 case SqlNodeType.LongCount:
905                 case SqlNodeType.Max:
906                 case SqlNodeType.Min:
907                 case SqlNodeType.Sum:
908                 case SqlNodeType.Avg:
909                 case SqlNodeType.Stddev:
910                 case SqlNodeType.Convert:
911                 case SqlNodeType.ValueOf:
912                 case SqlNodeType.Treat:
913                 case SqlNodeType.OuterJoinedValue:
914                 case SqlNodeType.ClrLength:
915                     break;
916                 default:
917                     throw Error.UnexpectedNode(nt);
918             }
919             this.Operand = expr;
920             this.method = method;
921         }
922 
923         internal SqlExpression Operand {
924             get { return this.operand; }
925             set {
926                 if (value == null && (this.NodeType != SqlNodeType.Count && this.NodeType != SqlNodeType.LongCount))
927                     throw Error.ArgumentNull("value");
928                 this.operand = value;
929             }
930         }
931 
932         internal MethodInfo Method {
933             get { return this.method; }
934         }
935     }
936 
937     internal class SqlBinary : SqlSimpleTypeExpression {
938         private SqlExpression left;
939         private SqlExpression right;
940         private MethodInfo method;
941 
942         [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.")]
SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right)943         internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right)
944             : this(nt, clrType, sqlType, left, right, null) {
945         }
946 
SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method)947         internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method)
948             : base(nt, clrType, sqlType, right.SourceExpression) {
949             switch (nt) {
950                 case SqlNodeType.Add:
951                 case SqlNodeType.Sub:
952                 case SqlNodeType.Mul:
953                 case SqlNodeType.Div:
954                 case SqlNodeType.Mod:
955                 case SqlNodeType.BitAnd:
956                 case SqlNodeType.BitOr:
957                 case SqlNodeType.BitXor:
958                 case SqlNodeType.And:
959                 case SqlNodeType.Or:
960                 case SqlNodeType.GE:
961                 case SqlNodeType.GT:
962                 case SqlNodeType.LE:
963                 case SqlNodeType.LT:
964                 case SqlNodeType.EQ:
965                 case SqlNodeType.NE:
966                 case SqlNodeType.EQ2V:
967                 case SqlNodeType.NE2V:
968                 case SqlNodeType.Concat:
969                 case SqlNodeType.Coalesce:
970                     break;
971                 default:
972                     throw Error.UnexpectedNode(nt);
973             }
974             this.Left = left;
975             this.Right = right;
976             this.method = method;
977         }
978 
979         internal SqlExpression Left {
980             get { return this.left; }
981             set {
982                 if (value == null)
983                     throw Error.ArgumentNull("value");
984                 this.left = value;
985             }
986         }
987 
988         internal SqlExpression Right {
989             get { return this.right; }
990             set {
991                 if (value == null)
992                     throw Error.ArgumentNull("value");
993                 this.right = value;
994             }
995         }
996 
997         internal MethodInfo Method {
998             get { return this.method; }
999         }
1000     }
1001 
1002     internal class SqlBetween : SqlSimpleTypeExpression {
1003         SqlExpression expression;
1004         SqlExpression start;
1005         SqlExpression end;
1006 
SqlBetween(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression start, SqlExpression end, Expression source)1007         internal SqlBetween(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression start, SqlExpression end, Expression source)
1008             : base(SqlNodeType.Between, clrType, sqlType, source) {
1009             this.expression = expr;
1010             this.start = start;
1011             this.end = end;
1012         }
1013 
1014         internal SqlExpression Expression {
1015             get { return this.expression; }
1016             set { this.expression = value; }
1017         }
1018 
1019         internal SqlExpression Start {
1020             get { return this.start; }
1021             set { this.start = value; }
1022         }
1023 
1024         internal SqlExpression End {
1025             get { return this.end; }
1026             set { this.end = value; }
1027         }
1028     }
1029 
1030     internal class SqlIn : SqlSimpleTypeExpression {
1031         private SqlExpression expression;
1032         private List<SqlExpression> values;
1033 
SqlIn(Type clrType, ProviderType sqlType, SqlExpression expression, IEnumerable<SqlExpression> values, Expression sourceExpression)1034         internal SqlIn(Type clrType, ProviderType sqlType, SqlExpression expression, IEnumerable<SqlExpression> values, Expression sourceExpression)
1035             :base(SqlNodeType.In, clrType, sqlType, sourceExpression) {
1036             this.expression = expression;
1037             this.values = values != null ? new List<SqlExpression>(values) : new List<SqlExpression>(0);
1038         }
1039 
1040         internal SqlExpression Expression {
1041             get { return this.expression; }
1042             set {
1043                 if (value == null) {
1044                     throw Error.ArgumentNull("value");
1045                 }
1046                 this.expression = value;
1047             }
1048         }
1049         internal List<SqlExpression> Values {
1050             get { return this.values; }
1051         }
1052     }
1053 
1054     internal class SqlLike : SqlSimpleTypeExpression {
1055         private SqlExpression expression;
1056         private SqlExpression pattern;
1057         private SqlExpression escape;
1058 
SqlLike(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression pattern, SqlExpression escape, Expression source)1059         internal SqlLike(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression pattern, SqlExpression escape, Expression source)
1060             : base(SqlNodeType.Like, clrType, sqlType, source) {
1061             if (expr == null)
1062                 throw Error.ArgumentNull("expr");
1063             if (pattern == null)
1064                 throw Error.ArgumentNull("pattern");
1065             this.Expression = expr;
1066             this.Pattern = pattern;
1067             this.Escape = escape;
1068         }
1069 
1070         internal SqlExpression Expression {
1071             get { return this.expression; }
1072             set {
1073                 if (value == null)
1074                     throw Error.ArgumentNull("value");
1075                 if (value.ClrType != typeof(string))
1076                     throw Error.ArgumentWrongType("value", "string", value.ClrType);
1077                 this.expression = value;
1078             }
1079         }
1080 
1081         internal SqlExpression Pattern {
1082             get { return this.pattern; }
1083             set {
1084                 if (value == null)
1085                     throw Error.ArgumentNull("value");
1086                 if (value.ClrType != typeof(string))
1087                     throw Error.ArgumentWrongType("value", "string", value.ClrType);
1088                 this.pattern = value;
1089             }
1090         }
1091 
1092         internal SqlExpression Escape {
1093             get { return this.escape; }
1094             set {
1095                 if (value != null && value.ClrType != typeof(string))
1096                     throw Error.ArgumentWrongType("value", "string", value.ClrType);
1097                 this.escape = value;
1098             }
1099         }
1100     }
1101 
1102     internal class SqlWhen {
1103         private SqlExpression matchExpression;
1104         private SqlExpression valueExpression;
1105 
SqlWhen(SqlExpression match, SqlExpression value)1106         internal SqlWhen(SqlExpression match, SqlExpression value) {
1107             // 'match' may be null when this when represents the ELSE condition.
1108             if (value == null)
1109                 throw Error.ArgumentNull("value");
1110             this.Match = match;
1111             this.Value = value;
1112         }
1113 
1114         internal SqlExpression Match {
1115             get { return this.matchExpression; }
1116             set {
1117                 if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType
1118                     // Exception: bool types, because predicates can have type bool or bool?
1119                     && !TypeSystem.GetNonNullableType(this.matchExpression.ClrType).Equals(typeof(bool))
1120                     && !TypeSystem.GetNonNullableType(value.ClrType).Equals(typeof(bool)))
1121                     throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
1122                 this.matchExpression = value;
1123             }
1124         }
1125 
1126         internal SqlExpression Value {
1127             get { return this.valueExpression; }
1128             set {
1129                 if (value == null)
1130                     throw Error.ArgumentNull("value");
1131                 if (this.valueExpression != null && !this.valueExpression.ClrType.IsAssignableFrom(value.ClrType))
1132                     throw Error.ArgumentWrongType("value", this.valueExpression.ClrType, value.ClrType);
1133                 this.valueExpression = value;
1134             }
1135         }
1136     }
1137 
1138     /*
1139      * Searched CASE function:
1140      * CASE
1141      * WHEN BooleanExpression THEN resultExpression
1142      * [ ...n ]
1143      * [
1144      * ELSE elseResultExpression
1145      * ]
1146      * END
1147      */
1148     internal class SqlSearchedCase : SqlExpression {
1149         private List<SqlWhen> whens;
1150         private SqlExpression @else;
1151 
SqlSearchedCase(Type clrType, IEnumerable<SqlWhen> whens, SqlExpression @else, Expression sourceExpression)1152         internal SqlSearchedCase(Type clrType, IEnumerable<SqlWhen> whens, SqlExpression @else, Expression sourceExpression)
1153             : base(SqlNodeType.SearchedCase, clrType, sourceExpression) {
1154             if (whens == null)
1155                 throw Error.ArgumentNull("whens");
1156             this.whens = new List<SqlWhen>(whens);
1157             if (this.whens.Count == 0)
1158                 throw Error.ArgumentOutOfRange("whens");
1159             this.Else = @else;
1160         }
1161 
1162         internal List<SqlWhen> Whens {
1163             get { return this.whens; }
1164         }
1165 
1166         internal SqlExpression Else {
1167             get { return this.@else; }
1168             set {
1169                 if (value == null)
1170                     throw Error.ArgumentNull("value");
1171                 if (this.@else != null && !this.@else.ClrType.IsAssignableFrom(value.ClrType))
1172                     throw Error.ArgumentWrongType("value", this.@else.ClrType, value.ClrType);
1173                 this.@else = value;
1174             }
1175         }
1176 
1177         internal override ProviderType SqlType {
1178             get { return this.whens[0].Value.SqlType; }
1179         }
1180     }
1181 
1182     /*
1183      * Simple CASE function:
1184      * CASE inputExpression
1185      * WHEN whenExpression THEN resultExpression
1186      * [ ...n ]
1187      * [
1188      * ELSE elseResultExpression
1189      * ]
1190      * END
1191      */
1192     internal class SqlSimpleCase : SqlExpression {
1193         private SqlExpression expression;
1194         private List<SqlWhen> whens = new List<SqlWhen>();
1195 
SqlSimpleCase(Type clrType, SqlExpression expr, IEnumerable<SqlWhen> whens, Expression sourceExpression)1196         internal SqlSimpleCase(Type clrType, SqlExpression expr, IEnumerable<SqlWhen> whens, Expression sourceExpression)
1197             : base(SqlNodeType.SimpleCase, clrType, sourceExpression) {
1198             this.Expression = expr;
1199             if (whens == null)
1200                 throw Error.ArgumentNull("whens");
1201             this.whens.AddRange(whens);
1202             if (this.whens.Count == 0)
1203                 throw Error.ArgumentOutOfRange("whens");
1204         }
1205 
1206         internal SqlExpression Expression {
1207             get { return this.expression; }
1208             set {
1209                 if (value == null)
1210                     throw Error.ArgumentNull("value");
1211                 if (this.expression != null && this.expression.ClrType != value.ClrType)
1212                     throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
1213                 this.expression = value;
1214             }
1215         }
1216 
1217         internal List<SqlWhen> Whens {
1218             get { return this.whens; }
1219         }
1220 
1221         internal override ProviderType SqlType {
1222             get { return this.whens[0].Value.SqlType; }
1223         }
1224     }
1225 
1226     /// <summary>
1227     /// A case statement that must be evaluated on the client. For example, a case statement
1228     /// that contains values of LINK, Element, or Multi-set are not directly handleable by
1229     /// SQL.
1230     ///
1231     /// CASE inputExpression
1232     /// WHEN whenExpression THEN resultExpression
1233     /// [ ...n ]
1234     /// END
1235     /// </summary>
1236     internal class SqlClientCase : SqlExpression {
1237         private SqlExpression expression;
1238         private List<SqlClientWhen> whens = new List<SqlClientWhen>();
1239 
SqlClientCase(Type clrType, SqlExpression expr, IEnumerable<SqlClientWhen> whens, Expression sourceExpression)1240         internal SqlClientCase(Type clrType, SqlExpression expr, IEnumerable<SqlClientWhen> whens, Expression sourceExpression)
1241             : base(SqlNodeType.ClientCase, clrType, sourceExpression) {
1242             this.Expression = expr;
1243             if (whens == null)
1244                 throw Error.ArgumentNull("whens");
1245             this.whens.AddRange(whens);
1246             if (this.whens.Count == 0)
1247                 throw Error.ArgumentOutOfRange("whens");
1248         }
1249 
1250         internal SqlExpression Expression {
1251             get { return this.expression; }
1252             set {
1253                 if (value == null)
1254                     throw Error.ArgumentNull("value");
1255                 if (this.expression != null && this.expression.ClrType != value.ClrType)
1256                     throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
1257                 this.expression = value;
1258             }
1259         }
1260 
1261         internal List<SqlClientWhen> Whens {
1262             get { return this.whens; }
1263         }
1264 
1265         internal override ProviderType SqlType {
1266             get { return this.whens[0].Value.SqlType; }
1267         }
1268     }
1269 
1270     /// <summary>
1271     /// A single WHEN clause for ClientCase.
1272     /// </summary>
1273     internal class SqlClientWhen {
1274         private SqlExpression matchExpression;
1275         private SqlExpression matchValue;
1276 
SqlClientWhen(SqlExpression match, SqlExpression value)1277         internal SqlClientWhen(SqlExpression match, SqlExpression value) {
1278             // 'match' may be null when this when represents the ELSE condition.
1279             if (value == null)
1280                 throw Error.ArgumentNull("value");
1281             this.Match = match;
1282             this.Value = value;
1283         }
1284 
1285         internal SqlExpression Match {
1286             get { return this.matchExpression; }
1287             set {
1288                 if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType)
1289                     throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
1290                 this.matchExpression = value;
1291             }
1292         }
1293 
1294         internal SqlExpression Value {
1295             get { return this.matchValue; }
1296             set {
1297                 if (value == null)
1298                     throw Error.ArgumentNull("value");
1299                 if (this.matchValue != null && this.matchValue.ClrType != value.ClrType)
1300                     throw Error.ArgumentWrongType("value", this.matchValue.ClrType, value.ClrType);
1301                 this.matchValue = value;
1302             }
1303         }
1304     }
1305 
1306     /// <summary>
1307     /// Represents the construction of an object in abstract 'super sql'.
1308     /// The type may be polymorphic. A discriminator field is used to determine
1309     /// which type in a hierarchy should be instantiated.
1310     /// In the common degenerate case where the inheritance hierarchy is 1-deep
1311     /// the discriminator will be a constant SqlValue and there will be one
1312     /// type-case-when corresponding to that type.
1313     /// </summary>
1314     internal class SqlTypeCase : SqlExpression {
1315         private MetaType rowType;
1316         private SqlExpression discriminator;
1317         private List<SqlTypeCaseWhen> whens = new List<SqlTypeCaseWhen>();
1318         ProviderType sqlType;
1319 
SqlTypeCase(Type clrType, ProviderType sqlType, MetaType rowType, SqlExpression discriminator, IEnumerable<SqlTypeCaseWhen> whens, Expression sourceExpression)1320         internal SqlTypeCase(Type clrType, ProviderType sqlType, MetaType rowType, SqlExpression discriminator, IEnumerable<SqlTypeCaseWhen> whens, Expression sourceExpression)
1321             : base(SqlNodeType.TypeCase, clrType, sourceExpression) {
1322             this.Discriminator = discriminator;
1323             if (whens == null)
1324                 throw Error.ArgumentNull("whens");
1325             this.whens.AddRange(whens);
1326             if (this.whens.Count == 0)
1327                 throw Error.ArgumentOutOfRange("whens");
1328             this.sqlType = sqlType;
1329             this.rowType = rowType;
1330         }
1331 
1332         internal SqlExpression Discriminator {
1333             get { return this.discriminator; }
1334             set {
1335                 if (value == null)
1336                     throw Error.ArgumentNull("value");
1337                 if (this.discriminator != null && this.discriminator.ClrType != value.ClrType)
1338                     throw Error.ArgumentWrongType("value", this.discriminator.ClrType, value.ClrType);
1339                 this.discriminator = value;
1340             }
1341         }
1342 
1343         internal List<SqlTypeCaseWhen> Whens {
1344             get { return this.whens; }
1345         }
1346 
1347         internal override ProviderType SqlType {
1348             get { return sqlType; }
1349         }
1350 
1351         internal MetaType RowType {
1352             get { return this.rowType; }
1353         }
1354     }
1355 
1356     /// <summary>
1357     /// Represents one choice of object instantiation type in a type case.
1358     /// When 'match' is the same as type case Discriminator then the corresponding
1359     /// type binding is the one used for instantiation.
1360     /// </summary>
1361     internal class SqlTypeCaseWhen {
1362         private SqlExpression match;
1363         private SqlExpression @new;
1364 
SqlTypeCaseWhen(SqlExpression match, SqlExpression typeBinding)1365         internal SqlTypeCaseWhen(SqlExpression match, SqlExpression typeBinding) {
1366             this.Match = match;
1367             this.TypeBinding = typeBinding;
1368         }
1369         internal SqlExpression Match {
1370             get { return this.match; }
1371             set {
1372                 if (this.match != null && value != null && this.match.ClrType != value.ClrType)
1373                     throw Error.ArgumentWrongType("value", this.match.ClrType, value.ClrType);
1374                 this.match = value;
1375             }
1376         }
1377         internal SqlExpression TypeBinding {
1378             get { return this.@new; }
1379             set { this.@new = value; }
1380         }
1381     }
1382 
1383     internal class SqlValue : SqlSimpleTypeExpression {
1384         private object value;
1385         private bool isClient;
1386 
SqlValue(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression)1387         internal SqlValue(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression)
1388             : base(SqlNodeType.Value, clrType, sqlType, sourceExpression) {
1389             this.value = value;
1390             this.isClient = isClientSpecified;
1391         }
1392 
1393         internal object Value {
1394             get { return this.value; }
1395         }
1396 
1397         internal bool IsClientSpecified {
1398             get { return this.isClient; }
1399         }
1400     }
1401 
1402     internal class SqlParameter : SqlSimpleTypeExpression {
1403         private string name;
1404         private System.Data.ParameterDirection direction;
1405 
SqlParameter(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)1406         internal SqlParameter(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)
1407             : base(SqlNodeType.Parameter, clrType, sqlType, sourceExpression) {
1408             if (name == null)
1409                 throw Error.ArgumentNull("name");
1410             if (typeof(Type).IsAssignableFrom(clrType))
1411                 throw Error.ArgumentWrongValue("clrType");
1412             this.name = name;
1413             this.direction = System.Data.ParameterDirection.Input;
1414         }
1415 
1416         internal string Name {
1417             get { return this.name; }
1418         }
1419 
1420         internal System.Data.ParameterDirection Direction {
1421             get { return this.direction; }
1422             set { this.direction = value; }
1423         }
1424     }
1425 
1426     internal class SqlVariable : SqlSimpleTypeExpression {
1427         private string name;
1428 
SqlVariable(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)1429         internal SqlVariable(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)
1430             : base(SqlNodeType.Variable, clrType, sqlType, sourceExpression) {
1431             if (name == null)
1432                 throw Error.ArgumentNull("name");
1433             this.name = name;
1434         }
1435 
1436         internal string Name {
1437             get { return this.name; }
1438         }
1439     }
1440 
1441     internal class SqlMember : SqlSimpleTypeExpression {
1442         private SqlExpression expression;
1443         private MemberInfo member;
1444 
SqlMember(Type clrType, ProviderType sqlType, SqlExpression expr, MemberInfo member)1445         internal SqlMember(Type clrType, ProviderType sqlType, SqlExpression expr, MemberInfo member)
1446             : base(SqlNodeType.Member, clrType, sqlType, expr.SourceExpression) {
1447             this.member = member;
1448             this.Expression = expr;
1449         }
1450 
1451         internal MemberInfo Member {
1452             get { return this.member; }
1453         }
1454 
1455         internal SqlExpression Expression {
1456             get {
1457                 return this.expression;
1458             }
1459             set {
1460                 if (value == null)
1461                     throw Error.ArgumentNull("value");
1462                 if (!this.member.ReflectedType.IsAssignableFrom(value.ClrType) &&
1463                     !value.ClrType.IsAssignableFrom(this.member.ReflectedType))
1464                     throw Error.MemberAccessIllegal(this.member, this.member.ReflectedType, value.ClrType);
1465                 this.expression = value;
1466             }
1467         }
1468     }
1469 
1470     internal class SqlColumn : SqlExpression {
1471         private SqlAlias alias;
1472         private string name;
1473         private int ordinal;
1474         private MetaDataMember member;
1475         private SqlExpression expression;
1476         private ProviderType sqlType;
1477 
SqlColumn(Type clrType, ProviderType sqlType, string name, MetaDataMember member, SqlExpression expr, Expression sourceExpression)1478         internal SqlColumn(Type clrType, ProviderType sqlType, string name, MetaDataMember member, SqlExpression expr, Expression sourceExpression)
1479             : base(SqlNodeType.Column, clrType, sourceExpression) {
1480             if (typeof(Type).IsAssignableFrom(clrType))
1481                 throw Error.ArgumentWrongValue("clrType");
1482             this.Name = name;
1483             this.member = member;
1484             this.Expression = expr;
1485             this.Ordinal = -1;
1486             if (sqlType == null)
1487                 throw Error.ArgumentNull("sqlType");
1488             this.sqlType = sqlType;
1489             System.Diagnostics.Debug.Assert(sqlType.CanBeColumn);
1490         }
1491 
SqlColumn(string name, SqlExpression expr)1492         internal SqlColumn(string name, SqlExpression expr)
1493             : this(expr.ClrType, expr.SqlType, name, null, expr, expr.SourceExpression) {
1494             System.Diagnostics.Debug.Assert(expr != null);
1495         }
1496 
1497         internal SqlAlias Alias {
1498             get { return this.alias; }
1499             set { this.alias = value; }
1500         }
1501 
1502         internal string Name {
1503             get { return this.name; }
1504             set { this.name = value; }
1505         }
1506 
1507         internal int Ordinal {
1508             get { return this.ordinal; }
1509             set { this.ordinal = value; }
1510         }
1511 
1512         internal MetaDataMember MetaMember {
1513             get { return this.member; }
1514         }
1515 
1516         /// <summary>
1517         /// Set the column's Expression. This can change the type of the column.
1518         /// </summary>
1519         internal SqlExpression Expression {
1520             get {
1521                 return this.expression;
1522             }
1523             set {
1524                 if (value != null) {
1525                     if (!this.ClrType.IsAssignableFrom(value.ClrType))
1526                         throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
1527                     SqlColumnRef cref = value as SqlColumnRef;
1528                     if (cref != null && cref.Column == this)
1529                         throw Error.ColumnCannotReferToItself();
1530                 }
1531                 this.expression = value;
1532             }
1533         }
1534 
1535         internal override ProviderType SqlType {
1536             get {
1537                 if (this.expression != null)
1538                     return this.expression.SqlType;
1539                 return this.sqlType;
1540             }
1541         }
1542     }
1543 
1544     internal class SqlColumnRef : SqlExpression {
1545         private SqlColumn column;
SqlColumnRef(SqlColumn col)1546         internal SqlColumnRef(SqlColumn col)
1547             : base(SqlNodeType.ColumnRef, col.ClrType, col.SourceExpression) {
1548             this.column = col;
1549         }
1550 
1551         internal SqlColumn Column {
1552             get { return this.column; }
1553         }
1554 
1555         internal override ProviderType SqlType {
1556             get { return this.column.SqlType; }
1557         }
1558 
Equals(object obj)1559         public override bool Equals(object obj) {
1560             SqlColumnRef cref = obj as SqlColumnRef;
1561             return cref != null && cref.Column == this.column;
1562         }
1563 
GetHashCode()1564         public override int GetHashCode() {
1565             return this.column.GetHashCode();
1566         }
1567 
GetRootColumn()1568         internal SqlColumn GetRootColumn() {
1569             SqlColumn c = this.column;
1570             while (c.Expression != null && c.Expression.NodeType == SqlNodeType.ColumnRef) {
1571                 c = ((SqlColumnRef)c.Expression).Column;
1572             }
1573             return c;
1574         }
1575     }
1576 
1577     internal class SqlRow : SqlNode {
1578         private List<SqlColumn> columns;
1579 
SqlRow(Expression sourceExpression)1580         internal SqlRow(Expression sourceExpression)
1581             : base(SqlNodeType.Row, sourceExpression) {
1582             this.columns = new List<SqlColumn>();
1583         }
1584 
1585         internal List<SqlColumn> Columns {
1586             get { return this.columns; }
1587         }
1588 
Find(string name)1589         internal SqlColumn Find(string name) {
1590             foreach (SqlColumn c in this.columns) {
1591                 if (name == c.Name)
1592                     return c;
1593             }
1594             return null;
1595         }
1596     }
1597 
1598     internal class SqlMemberAssign : SqlNode {
1599         private MemberInfo member;
1600         private SqlExpression expression;
1601 
SqlMemberAssign(MemberInfo member, SqlExpression expr)1602         internal SqlMemberAssign(MemberInfo member, SqlExpression expr)
1603             : base(SqlNodeType.MemberAssign, expr.SourceExpression) {
1604             if (member == null)
1605                 throw Error.ArgumentNull("member");
1606             this.member = member;
1607             this.Expression = expr;
1608         }
1609 
1610         internal MemberInfo Member {
1611             get { return this.member; }
1612         }
1613 
1614         internal SqlExpression Expression {
1615             get { return this.expression; }
1616             set {
1617                 if (value == null)
1618                     throw Error.ArgumentNull("value");
1619                 this.expression = value;
1620             }
1621         }
1622     }
1623 
1624     internal class SqlGrouping : SqlSimpleTypeExpression {
1625         private SqlExpression key;
1626         private SqlExpression group;
1627 
SqlGrouping(Type clrType, ProviderType sqlType, SqlExpression key, SqlExpression group, Expression sourceExpression)1628         internal SqlGrouping(Type clrType, ProviderType sqlType, SqlExpression key, SqlExpression group, Expression sourceExpression)
1629             : base(SqlNodeType.Grouping, clrType, sqlType, sourceExpression) {
1630             if (key == null) throw Error.ArgumentNull("key");
1631             if (group == null) throw Error.ArgumentNull("group");
1632             this.key = key;
1633             this.group = group;
1634         }
1635 
1636         internal SqlExpression Key {
1637             get { return this.key; }
1638             set {
1639                 if (value == null)
1640                     throw Error.ArgumentNull("value");
1641                 if (!this.key.ClrType.IsAssignableFrom(value.ClrType)
1642                     && !value.ClrType.IsAssignableFrom(this.key.ClrType))
1643                     throw Error.ArgumentWrongType("value", this.key.ClrType, value.ClrType);
1644                 this.key = value;
1645             }
1646         }
1647 
1648         internal SqlExpression Group {
1649             get { return this.group; }
1650             set {
1651                 if (value == null)
1652                     throw Error.ArgumentNull("value");
1653                 if (value.ClrType != this.group.ClrType)
1654                     throw Error.ArgumentWrongType("value", this.group.ClrType, value.ClrType);
1655                 this.group = value;
1656             }
1657         }
1658     }
1659 
1660     internal class SqlNew : SqlSimpleTypeExpression {
1661         private MetaType metaType;
1662         private ConstructorInfo constructor;
1663         private List<SqlExpression> args;
1664         private List<MemberInfo> argMembers;
1665         private List<SqlMemberAssign> members;
1666 
SqlNew(MetaType metaType, ProviderType sqlType, ConstructorInfo cons, IEnumerable<SqlExpression> args, IEnumerable<MemberInfo> argMembers, IEnumerable<SqlMemberAssign> members, Expression sourceExpression)1667         internal SqlNew(MetaType metaType, ProviderType sqlType, ConstructorInfo cons, IEnumerable<SqlExpression> args, IEnumerable<MemberInfo> argMembers, IEnumerable<SqlMemberAssign> members, Expression sourceExpression)
1668             : base(SqlNodeType.New, metaType.Type, sqlType, sourceExpression) {
1669             this.metaType = metaType;
1670 
1671             if (cons == null && metaType.Type.IsClass) { // structs do not need to have a constructor
1672                 throw Error.ArgumentNull("cons");
1673             }
1674             this.constructor = cons;
1675             this.args = new List<SqlExpression>();
1676             this.argMembers = new List<MemberInfo>();
1677             this.members = new List<SqlMemberAssign>();
1678             if (args != null) {
1679                 this.args.AddRange(args);
1680             }
1681             if (argMembers != null) {
1682                 this.argMembers.AddRange(argMembers);
1683             }
1684             if (members != null) {
1685                 this.members.AddRange(members);
1686             }
1687         }
1688 
1689         internal MetaType MetaType {
1690             get { return this.metaType; }
1691         }
1692 
1693         internal ConstructorInfo Constructor {
1694             get { return this.constructor; }
1695         }
1696 
1697         internal List<SqlExpression> Args {
1698             get { return this.args; }
1699         }
1700 
1701         internal List<MemberInfo> ArgMembers {
1702             get { return this.argMembers; }
1703         }
1704 
1705         internal List<SqlMemberAssign> Members {
1706             get { return this.members; }
1707         }
1708 
Find(MemberInfo mi)1709         internal SqlExpression Find(MemberInfo mi) {
1710             for (int i = 0, n = this.argMembers.Count; i < n; i++) {
1711                 MemberInfo argmi = this.argMembers[i];
1712                 if (argmi.Name == mi.Name) {
1713                     return this.args[i];
1714                 }
1715             }
1716 
1717             foreach (SqlMemberAssign ma in this.Members) {
1718                 if (ma.Member.Name == mi.Name) {
1719                     return ma.Expression;
1720                 }
1721             }
1722 
1723             return null;
1724         }
1725     }
1726 
1727     internal class SqlMethodCall : SqlSimpleTypeExpression {
1728         private MethodInfo method;
1729         private SqlExpression obj;
1730         private List<SqlExpression> arguments;
1731 
SqlMethodCall(Type clrType, ProviderType sqlType, MethodInfo method, SqlExpression obj, IEnumerable<SqlExpression> args, Expression sourceExpression)1732         internal SqlMethodCall(Type clrType, ProviderType sqlType, MethodInfo method, SqlExpression obj, IEnumerable<SqlExpression> args, Expression sourceExpression)
1733             : base(SqlNodeType.MethodCall, clrType, sqlType, sourceExpression) {
1734             if (method == null)
1735                 throw Error.ArgumentNull("method");
1736             this.method = method;
1737             this.Object = obj;
1738             this.arguments = new List<SqlExpression>();
1739             if (args != null)
1740                 this.arguments.AddRange(args);
1741         }
1742 
1743         internal MethodInfo Method {
1744             get { return this.method; }
1745         }
1746 
1747         internal SqlExpression Object {
1748             get { return this.obj; }
1749             set {
1750                 if (value == null && !this.method.IsStatic)
1751                     throw Error.ArgumentNull("value");
1752                 if (value != null && !this.method.DeclaringType.IsAssignableFrom(value.ClrType))
1753                     throw Error.ArgumentWrongType("value", this.method.DeclaringType, value.ClrType);
1754                 this.obj = value;
1755             }
1756         }
1757 
1758         internal List<SqlExpression> Arguments {
1759             get { return this.arguments; }
1760         }
1761     }
1762 
1763     internal class SqlIncludeScope : SqlNode {
1764         SqlNode child;
SqlIncludeScope(SqlNode child, Expression sourceExpression)1765         internal SqlIncludeScope(SqlNode child, Expression sourceExpression)
1766             : base(SqlNodeType.IncludeScope, sourceExpression) {
1767             this.child = child;
1768         }
1769         internal SqlNode Child {
1770             get {return this.child;}
1771             set {this.child = value;}
1772         }
1773     }
1774 
1775     internal class SqlClientArray : SqlSimpleTypeExpression {
1776         private List<SqlExpression> expressions;
1777 
SqlClientArray(Type clrType, ProviderType sqlType, SqlExpression[ ] exprs, Expression sourceExpression)1778         internal SqlClientArray(Type clrType, ProviderType sqlType, SqlExpression[ ] exprs, Expression sourceExpression)
1779             : base(SqlNodeType.ClientArray, clrType, sqlType, sourceExpression) {
1780             this.expressions = new List<SqlExpression>();
1781             if (exprs != null)
1782                 this.Expressions.AddRange(exprs);
1783         }
1784 
1785         internal List<SqlExpression> Expressions {
1786             get { return this.expressions; }
1787         }
1788     }
1789 
1790     internal class SqlLink : SqlSimpleTypeExpression {
1791         private MetaType rowType;
1792         private SqlExpression expression;
1793         private MetaDataMember member;
1794         private List<SqlExpression> keyExpressions;
1795         private SqlExpression expansion;
1796         private object id;
1797 
SqlLink(object id, MetaType rowType, Type clrType, ProviderType sqlType, SqlExpression expression, MetaDataMember member, IEnumerable<SqlExpression> keyExpressions, SqlExpression expansion, Expression sourceExpression)1798         internal SqlLink(object id, MetaType rowType, Type clrType, ProviderType sqlType, SqlExpression expression, MetaDataMember member, IEnumerable<SqlExpression> keyExpressions, SqlExpression expansion, Expression sourceExpression)
1799             : base(SqlNodeType.Link, clrType, sqlType, sourceExpression) {
1800             this.id = id;
1801             this.rowType = rowType;
1802             this.expansion = expansion;
1803             this.expression = expression;
1804             this.member = member;
1805             this.keyExpressions = new List<SqlExpression>();
1806             if (keyExpressions != null)
1807                 this.keyExpressions.AddRange(keyExpressions);
1808         }
1809 
1810         internal MetaType RowType {
1811             get { return this.rowType; }
1812         }
1813 
1814         internal SqlExpression Expansion {
1815             get { return this.expansion; }
1816             set { this.expansion = value; }
1817         }
1818 
1819 
1820         internal SqlExpression Expression {
1821             get { return this.expression; }
1822             set { this.expression = value; }
1823         }
1824 
1825         internal MetaDataMember Member {
1826             get { return this.member; }
1827         }
1828 
1829         internal List<SqlExpression> KeyExpressions {
1830             get { return this.keyExpressions; }
1831         }
1832 
1833         internal object Id {
1834             get { return this.id; }
1835         }
1836     }
1837 
1838     internal class SqlExprSet : SqlExpression {
1839         private List<SqlExpression> expressions;
1840 
SqlExprSet(Type clrType, IEnumerable <SqlExpression> exprs, Expression sourceExpression)1841         internal SqlExprSet(Type clrType, IEnumerable <SqlExpression> exprs, Expression sourceExpression)
1842             : base(SqlNodeType.ExprSet, clrType, sourceExpression) {
1843             this.expressions = new List<SqlExpression>(exprs);
1844         }
1845 
1846         internal List<SqlExpression> Expressions {
1847             get { return this.expressions; }
1848         }
1849 
1850         /// <summary>
1851         /// Get the first non-set expression of the set by drilling
1852         /// down the left expressions.
1853         /// </summary>
GetFirstExpression()1854         internal SqlExpression GetFirstExpression() {
1855             SqlExpression expr = expressions[0];
1856             while (expr is SqlExprSet) {
1857                 expr = ((SqlExprSet)expr).Expressions[0];
1858             }
1859             return expr;
1860         }
1861 
1862         internal override ProviderType SqlType {
1863             get { return this.expressions[0].SqlType; }
1864         }
1865     }
1866 
1867     internal class SqlSubSelect : SqlSimpleTypeExpression {
1868         private SqlSelect select;
1869 
SqlSubSelect(SqlNodeType nt , Type clrType, ProviderType sqlType , SqlSelect select)1870         internal SqlSubSelect(SqlNodeType nt , Type clrType, ProviderType sqlType , SqlSelect select)
1871             : base(nt, clrType, sqlType, select.SourceExpression) {
1872             switch (nt) {
1873                 case SqlNodeType.Multiset:
1874                 case SqlNodeType.ScalarSubSelect:
1875                 case SqlNodeType.Element:
1876                 case SqlNodeType.Exists:
1877                     break;
1878                 default:
1879                     throw Error.UnexpectedNode(nt);
1880             }
1881             this.Select = select;
1882         }
1883 
1884         internal SqlSelect Select {
1885             get { return this.select; }
1886             set {
1887                 if (value == null)
1888                     throw Error.ArgumentNull("value");
1889                 this.select = value;
1890             }
1891         }
1892     }
1893 
1894     internal class SqlClientQuery : SqlSimpleTypeExpression {
1895         private SqlSubSelect query;
1896         private List<SqlExpression> arguments;
1897         private List<SqlParameter> parameters;
1898         int ordinal;
1899 
SqlClientQuery(SqlSubSelect subquery)1900         internal SqlClientQuery(SqlSubSelect subquery)
1901             : base(SqlNodeType.ClientQuery, subquery.ClrType, subquery.SqlType, subquery.SourceExpression) {
1902             this.query = subquery;
1903             this.arguments = new List<SqlExpression>();
1904             this.parameters = new List<SqlParameter>();
1905         }
1906 
1907         internal SqlSubSelect Query {
1908             get { return this.query; }
1909             set {
1910                 if (value == null || (this.query != null && this.query.ClrType != value.ClrType))
1911                     throw Error.ArgumentWrongType(value, this.query.ClrType, value.ClrType);
1912                 this.query = value;
1913             }
1914         }
1915 
1916         internal List<SqlExpression> Arguments {
1917             get { return this.arguments; }
1918         }
1919 
1920         internal List<SqlParameter> Parameters {
1921             get { return this.parameters; }
1922         }
1923 
1924         internal int Ordinal {
1925             get { return this.ordinal; }
1926             set { this.ordinal = value; }
1927         }
1928     }
1929 
1930     internal class SqlJoinedCollection : SqlSimpleTypeExpression {
1931         private SqlExpression expression;
1932         private SqlExpression count;
1933 
SqlJoinedCollection(Type clrType, ProviderType sqlType, SqlExpression expression, SqlExpression count, Expression sourceExpression)1934         internal SqlJoinedCollection(Type clrType, ProviderType sqlType, SqlExpression expression, SqlExpression count, Expression sourceExpression)
1935             : base(SqlNodeType.JoinedCollection, clrType, sqlType, sourceExpression) {
1936             this.expression = expression;
1937             this.count = count;
1938         }
1939 
1940         internal SqlExpression Expression {
1941             get { return this.expression; }
1942             set {
1943                 if (value == null || this.expression != null && this.expression.ClrType != value.ClrType)
1944                     throw Error.ArgumentWrongType(value, this.expression.ClrType, value.ClrType);
1945                 this.expression = value;
1946             }
1947         }
1948 
1949         internal SqlExpression Count {
1950             get { return this.count; }
1951             set {
1952                 if (value == null)
1953                     throw Error.ArgumentNull("value");
1954                 if (value.ClrType != typeof(int))
1955                     throw Error.ArgumentWrongType(value, typeof(int), value.ClrType);
1956                 this.count = value;
1957             }
1958         }
1959     }
1960 
1961     internal class SqlUpdate : SqlStatement {
1962         private SqlSelect select;
1963         private List<SqlAssign> assignments;
1964 
SqlUpdate(SqlSelect select, IEnumerable<SqlAssign> assignments, Expression sourceExpression)1965         internal SqlUpdate(SqlSelect select, IEnumerable<SqlAssign> assignments, Expression sourceExpression)
1966             : base(SqlNodeType.Update, sourceExpression) {
1967             this.Select = select;
1968             this.assignments = new List<SqlAssign>(assignments);
1969         }
1970 
1971         internal SqlSelect Select {
1972             get { return this.select; }
1973             set {
1974                 if (value == null)
1975                     throw Error.ArgumentNull("value");
1976                 this.select = value;
1977             }
1978         }
1979 
1980         internal List<SqlAssign> Assignments {
1981             get { return this.assignments; }
1982         }
1983     }
1984 
1985     internal class SqlInsert : SqlStatement {
1986         private SqlTable table;
1987         private SqlRow row;
1988         private SqlExpression expression;
1989         private SqlColumn outputKey;
1990         private bool outputToLocal;
1991 
SqlInsert(SqlTable table, SqlExpression expr, Expression sourceExpression)1992         internal SqlInsert(SqlTable table, SqlExpression expr, Expression sourceExpression)
1993             : base(SqlNodeType.Insert, sourceExpression) {
1994             this.Table = table;
1995             this.Expression = expr;
1996             this.Row = new SqlRow(sourceExpression);
1997         }
1998 
1999         internal SqlTable Table {
2000             get { return this.table; }
2001             set {
2002                 if (value == null)
2003                     throw Error.ArgumentNull("null");
2004                 this.table = value;
2005             }
2006         }
2007 
2008         internal SqlRow Row {
2009             get { return this.row; }
2010             set { this.row = value; }
2011         }
2012 
2013         internal SqlExpression Expression {
2014             get { return this.expression; }
2015             set {
2016                 if (value == null)
2017                     throw Error.ArgumentNull("null");
2018                 if (!this.table.RowType.Type.IsAssignableFrom(value.ClrType))
2019                     throw Error.ArgumentWrongType("value", this.table.RowType, value.ClrType);
2020                 this.expression = value;
2021             }
2022         }
2023 
2024         internal SqlColumn OutputKey {
2025             get { return this.outputKey; }
2026             set { this.outputKey = value; }
2027         }
2028 
2029         internal bool OutputToLocal {
2030             get { return this.outputToLocal; }
2031             set { this.outputToLocal = value; }
2032         }
2033     }
2034 
2035     internal class SqlDelete : SqlStatement {
2036         private SqlSelect select;
2037 
SqlDelete(SqlSelect select, Expression sourceExpression)2038         internal SqlDelete(SqlSelect select, Expression sourceExpression)
2039             : base(SqlNodeType.Delete, sourceExpression) {
2040             this.Select = select;
2041         }
2042 
2043         internal SqlSelect Select {
2044             get { return this.select; }
2045             set {
2046                 if (value == null)
2047                     throw Error.ArgumentNull("value");
2048                 this.select = value;
2049             }
2050         }
2051     }
2052 
2053     internal class SqlBlock : SqlStatement {
2054         private List<SqlStatement> statements;
2055 
SqlBlock(Expression sourceExpression)2056         internal SqlBlock(Expression sourceExpression)
2057             : base(SqlNodeType.Block, sourceExpression) {
2058             this.statements = new List<SqlStatement>();
2059         }
2060 
2061         internal List<SqlStatement> Statements {
2062             get { return this.statements; }
2063         }
2064     }
2065 
2066     internal class SqlAssign : SqlStatement {
2067         private SqlExpression leftValue;
2068         private SqlExpression rightValue;
2069 
SqlAssign(SqlExpression lValue, SqlExpression rValue, Expression sourceExpression)2070         internal SqlAssign(SqlExpression lValue, SqlExpression rValue, Expression sourceExpression)
2071             : base(SqlNodeType.Assign, sourceExpression) {
2072             this.LValue = lValue;
2073             this.RValue = rValue;
2074         }
2075 
2076         internal SqlExpression LValue {
2077             get { return this.leftValue; }
2078             set {
2079                 if (value == null)
2080                     throw Error.ArgumentNull("value");
2081                 if (this.rightValue != null && !value.ClrType.IsAssignableFrom(this.rightValue.ClrType))
2082                     throw Error.ArgumentWrongType("value", this.rightValue.ClrType, value.ClrType);
2083                 this.leftValue = value;
2084             }
2085         }
2086 
2087         internal SqlExpression RValue {
2088             get { return this.rightValue; }
2089             set {
2090                 if (value == null)
2091                     throw Error.ArgumentNull("value");
2092                 if (this.leftValue != null && !this.leftValue.ClrType.IsAssignableFrom(value.ClrType))
2093                     throw Error.ArgumentWrongType("value", this.leftValue.ClrType, value.ClrType);
2094                 this.rightValue = value;
2095             }
2096         }
2097     }
2098 
2099     internal class SqlDoNotVisitExpression : SqlExpression {
2100         private SqlExpression expression;
2101 
SqlDoNotVisitExpression(SqlExpression expr)2102         internal SqlDoNotVisitExpression(SqlExpression expr)
2103             : base(SqlNodeType.DoNotVisit, expr.ClrType, expr.SourceExpression) {
2104             if (expr == null)
2105                 throw Error.ArgumentNull("expr");
2106             this.expression = expr;
2107         }
2108 
2109         internal SqlExpression Expression {
2110             get { return this.expression; }
2111         }
2112 
2113         internal override ProviderType SqlType {
2114             get { return this.expression.SqlType; }
2115         }
2116     }
2117 
2118     internal class SqlOptionalValue : SqlSimpleTypeExpression {
2119         private SqlExpression hasValue;
2120         private SqlExpression expressionValue;
2121 
SqlOptionalValue( SqlExpression hasValue, SqlExpression value)2122         internal SqlOptionalValue( SqlExpression hasValue, SqlExpression value)
2123             : base(SqlNodeType.OptionalValue, value.ClrType, value.SqlType, value.SourceExpression) {
2124             this.HasValue = hasValue;
2125             this.Value = value;
2126         }
2127 
2128         internal SqlExpression HasValue {
2129             get { return this.hasValue; }
2130             set {
2131                 if (value == null)
2132                     throw Error.ArgumentNull("value");
2133                 this.hasValue = value;
2134             }
2135         }
2136 
2137         internal SqlExpression Value {
2138             get { return this.expressionValue; }
2139             set {
2140                 if (value == null)
2141                     throw Error.ArgumentNull("value");
2142                 if (value.ClrType != this.ClrType)
2143                     throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
2144                 this.expressionValue = value;
2145             }
2146         }
2147     }
2148 
2149     internal class SqlFunctionCall : SqlSimpleTypeExpression {
2150         private string name;
2151         private List<SqlExpression> arguments;
2152 
SqlFunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression > args , Expression source)2153         internal SqlFunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression > args , Expression source)
2154             : this(SqlNodeType.FunctionCall, clrType , sqlType, name, args, source) {
2155         }
2156 
SqlFunctionCall(SqlNodeType nodeType, Type clrType, ProviderType sqlType, string name , IEnumerable <SqlExpression> args , Expression source)2157         internal SqlFunctionCall(SqlNodeType nodeType, Type clrType, ProviderType sqlType, string name , IEnumerable <SqlExpression> args , Expression source)
2158             : base(nodeType, clrType, sqlType, source) {
2159             this.name = name;
2160             this.arguments = new List<SqlExpression>(args);
2161         }
2162 
2163         internal string Name {
2164             get { return this.name; }
2165         }
2166 
2167         internal List<SqlExpression> Arguments {
2168             get { return this.arguments; }
2169         }
2170     }
2171 
2172     /// <summary>
2173     /// This class is used to represent a table value function.  It inherits normal function
2174     /// call functionality, and adds TVF specific members.
2175     /// </summary>
2176     internal class SqlTableValuedFunctionCall : SqlFunctionCall {
2177         private MetaType rowType;
2178         private List<SqlColumn> columns;
2179 
SqlTableValuedFunctionCall(MetaType rowType, Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression > args , Expression source)2180         internal SqlTableValuedFunctionCall(MetaType rowType, Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression > args , Expression source)
2181             : base(SqlNodeType.TableValuedFunctionCall, clrType , sqlType, name, args, source) {
2182             this.rowType = rowType;
2183             this.columns = new List<SqlColumn>();
2184         }
2185 
2186         internal MetaType RowType {
2187             get { return this.rowType; }
2188         }
2189 
2190         internal List<SqlColumn> Columns {
2191             get { return this.columns; }
2192         }
2193 
Find(string name)2194         internal SqlColumn Find(string name) {
2195             foreach (SqlColumn c in this.Columns) {
2196                 if (c.Name == name)
2197                     return c;
2198             }
2199             return null;
2200         }
2201 
2202     }
2203 
2204     internal class SqlSharedExpression : SqlExpression {
2205         private SqlExpression expr;
2206 
SqlSharedExpression(SqlExpression expr)2207         internal SqlSharedExpression(SqlExpression expr)
2208           : base(SqlNodeType.SharedExpression, expr.ClrType, expr.SourceExpression) {
2209             this.expr = expr;
2210         }
2211 
2212         internal SqlExpression Expression {
2213             get { return this.expr; }
2214             set {
2215                 if (value == null)
2216                     throw Error.ArgumentNull("value");
2217                 if (!this.ClrType.IsAssignableFrom(value.ClrType)
2218                     && !value.ClrType.IsAssignableFrom(this.ClrType))
2219                     throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
2220                 this.expr = value;
2221             }
2222         }
2223 
2224         internal override ProviderType SqlType {
2225             get { return this.expr.SqlType; }
2226         }
2227     }
2228 
2229     internal class SqlSharedExpressionRef : SqlExpression {
2230         private SqlSharedExpression expr;
2231 
SqlSharedExpressionRef(SqlSharedExpression expr)2232         internal SqlSharedExpressionRef(SqlSharedExpression expr)
2233             : base(SqlNodeType.SharedExpressionRef, expr.ClrType, expr.SourceExpression) {
2234             this.expr = expr;
2235         }
2236 
2237         internal SqlSharedExpression SharedExpression {
2238             get { return this.expr; }
2239         }
2240 
2241         internal override ProviderType SqlType {
2242             get { return this.expr.SqlType; }
2243         }
2244     }
2245 
2246     internal class SqlSimpleExpression : SqlExpression {
2247         private SqlExpression expr;
2248 
SqlSimpleExpression(SqlExpression expr)2249         internal SqlSimpleExpression(SqlExpression expr)
2250             : base(SqlNodeType.SimpleExpression, expr.ClrType, expr.SourceExpression) {
2251             this.expr = expr;
2252         }
2253 
2254         internal SqlExpression Expression {
2255             get { return this.expr; }
2256             set {
2257                 if (value == null)
2258                     throw Error.ArgumentNull("value");
2259                 if (!TypeSystem.GetNonNullableType(this.ClrType).IsAssignableFrom(TypeSystem.GetNonNullableType(value.ClrType)))
2260                     throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
2261                 this.expr = value;
2262             }
2263         }
2264 
2265         internal override ProviderType SqlType {
2266             get { return this.expr.SqlType; }
2267         }
2268     }
2269 
2270     internal class SqlClientParameter : SqlSimpleTypeExpression {
2271         // Expression<Func<object[], T>>
2272         LambdaExpression accessor;
SqlClientParameter(Type clrType, ProviderType sqlType, LambdaExpression accessor, Expression sourceExpression)2273         internal SqlClientParameter(Type clrType, ProviderType sqlType, LambdaExpression accessor, Expression sourceExpression):
2274             base(SqlNodeType.ClientParameter, clrType, sqlType, sourceExpression) {
2275             this.accessor = accessor;
2276         }
2277         internal LambdaExpression Accessor {
2278             get { return this.accessor; }
2279         }
2280     }
2281 }
2282