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