1 //--------------------------------------------------------------------- 2 // <copyright file="Ops.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 // 6 // @owner Microsoft 7 // @backupOwner Microsoft 8 //--------------------------------------------------------------------- 9 10 namespace System.Data.Query.InternalTrees 11 { 12 using System.Data.Metadata.Edm; 13 using System.Diagnostics; 14 15 /// <summary> 16 /// The operator types. Includes both scalar and relational operators, 17 /// and physical and logical operators, and rule operators 18 /// </summary> 19 internal enum OpType 20 { 21 #region ScalarOpType 22 /// <summary> 23 /// Constants 24 /// </summary> 25 Constant, 26 27 /// <summary> 28 /// An internally generated constant 29 /// </summary> 30 InternalConstant, 31 32 /// <summary> 33 /// An internally generated constant used as a null sentinel 34 /// </summary> 35 NullSentinel, 36 37 /// <summary> 38 /// A null constant 39 /// </summary> 40 Null, 41 42 /// <summary> 43 /// ConstantPredicate 44 /// </summary> 45 ConstantPredicate, 46 47 /// <summary> 48 /// A Var reference 49 /// </summary> 50 VarRef, 51 52 /// <summary> 53 /// GreaterThan 54 /// </summary> 55 GT, 56 57 /// <summary> 58 /// >= 59 /// </summary> 60 GE, 61 62 /// <summary> 63 /// Lessthan or equals 64 /// </summary> 65 LE, 66 67 /// <summary> 68 /// Less than 69 /// </summary> 70 LT, 71 72 /// <summary> 73 /// Equals 74 /// </summary> 75 EQ, 76 77 /// <summary> 78 /// Not equals 79 /// </summary> 80 NE, 81 82 /// <summary> 83 /// String comparison 84 /// </summary> 85 Like, 86 87 /// <summary> 88 /// Addition 89 /// </summary> 90 Plus, 91 92 /// <summary> 93 /// Subtraction 94 /// </summary> 95 Minus, 96 97 /// <summary> 98 /// Multiplication 99 /// </summary> 100 Multiply, 101 102 /// <summary> 103 /// Division 104 /// </summary> 105 Divide, 106 107 /// <summary> 108 /// Modulus 109 /// </summary> 110 Modulo, 111 112 /// <summary> 113 /// Unary Minus 114 /// </summary> 115 UnaryMinus, 116 117 /// <summary> 118 /// And 119 /// </summary> 120 And, 121 122 /// <summary> 123 /// Or 124 /// </summary> 125 Or, 126 127 /// <summary> 128 /// Not 129 /// </summary> 130 Not, 131 132 /// <summary> 133 /// is null 134 /// </summary> 135 IsNull, 136 137 /// <summary> 138 /// switched case expression 139 /// </summary> 140 Case, 141 142 /// <summary> 143 /// treat-as 144 /// </summary> 145 Treat, 146 147 /// <summary> 148 /// is-of 149 /// </summary> 150 IsOf, 151 152 /// <summary> 153 /// Cast 154 /// </summary> 155 Cast, 156 157 /// <summary> 158 /// Internal cast 159 /// </summary> 160 SoftCast, 161 162 /// <summary> 163 /// a basic aggregate 164 /// </summary> 165 Aggregate, 166 167 /// <summary> 168 /// function call 169 /// </summary> 170 Function, 171 172 /// <summary> 173 /// Reference to a "relationship" property 174 /// </summary> 175 RelProperty, 176 177 /// <summary> 178 /// property reference 179 /// </summary> 180 Property, 181 182 /// <summary> 183 /// entity constructor 184 /// </summary> 185 NewEntity, 186 187 /// <summary> 188 /// new instance constructor for a named type(other than multiset, record) 189 /// </summary> 190 NewInstance, 191 192 /// <summary> 193 /// new instance constructor for a named type and sub-types 194 /// </summary> 195 DiscriminatedNewEntity, 196 197 /// <summary> 198 /// Multiset constructor 199 /// </summary> 200 NewMultiset, 201 202 /// <summary> 203 /// record constructor 204 /// </summary> 205 NewRecord, 206 207 /// <summary> 208 /// Get the key from a Ref 209 /// </summary> 210 GetRefKey, 211 212 /// <summary> 213 /// Get the ref from an entity instance 214 /// </summary> 215 GetEntityRef, 216 217 /// <summary> 218 /// create a reference 219 /// </summary> 220 Ref, 221 222 /// <summary> 223 /// exists 224 /// </summary> 225 Exists, 226 227 /// <summary> 228 /// get the singleton element from a collection 229 /// </summary> 230 Element, 231 232 /// <summary> 233 /// Builds up a collection 234 /// </summary> 235 Collect, 236 237 /// <summary> 238 /// gets the target entity pointed at by a reference 239 /// </summary> 240 Deref, 241 242 /// <summary> 243 /// Traverse a relationship and get the references of the other end 244 /// </summary> 245 Navigate, 246 #endregion 247 248 #region RelOpType 249 /// <summary> 250 /// A table scan 251 /// </summary> 252 ScanTable, 253 /// <summary> 254 /// A view scan 255 /// </summary> 256 ScanView, 257 258 /// <summary> 259 /// Filter 260 /// </summary> 261 Filter, 262 263 /// <summary> 264 /// Project 265 /// </summary> 266 Project, 267 268 /// <summary> 269 /// InnerJoin 270 /// </summary> 271 InnerJoin, 272 273 /// <summary> 274 /// LeftOuterJoin 275 /// </summary> 276 LeftOuterJoin, 277 278 /// <summary> 279 /// FullOuter join 280 /// </summary> 281 FullOuterJoin, 282 283 /// <summary> 284 /// Cross join 285 /// </summary> 286 CrossJoin, 287 288 /// <summary> 289 /// cross apply 290 /// </summary> 291 CrossApply, 292 293 /// <summary> 294 /// outer apply 295 /// </summary> 296 OuterApply, 297 298 /// <summary> 299 /// Unnest 300 /// </summary> 301 Unnest, 302 303 /// <summary> 304 /// Sort 305 /// </summary> 306 Sort, 307 308 /// <summary> 309 /// Constrained Sort (physical paging - Limit and Skip) 310 /// </summary> 311 ConstrainedSort, 312 313 /// <summary> 314 /// GroupBy 315 /// </summary> 316 GroupBy, 317 318 /// <summary> 319 /// GroupByInto (projects the group as well) 320 /// </summary> 321 GroupByInto, 322 323 /// <summary> 324 /// UnionAll 325 /// </summary> 326 UnionAll, 327 /// <summary> 328 /// Intersect 329 /// </summary> 330 Intersect, 331 /// <summary> 332 /// Except 333 /// </summary> 334 Except, 335 336 /// <summary> 337 /// Distinct 338 /// </summary> 339 Distinct, 340 341 /// <summary> 342 /// Select a single row from a subquery 343 /// </summary> 344 SingleRow, 345 346 /// <summary> 347 /// A table with exactly one row 348 /// </summary> 349 SingleRowTable, 350 351 #endregion 352 353 #region AncillaryOpType 354 /// <summary> 355 /// Variable definition 356 /// </summary> 357 VarDef, 358 /// <summary> 359 /// List of variable definitions 360 /// </summary> 361 VarDefList, 362 #endregion 363 364 #region RulePatternOpType 365 /// <summary> 366 /// Leaf 367 /// </summary> 368 Leaf, 369 #endregion 370 371 #region PhysicalOpType 372 /// <summary> 373 /// Physical Project 374 /// </summary> 375 PhysicalProject, 376 377 /// <summary> 378 /// single-stream nest aggregation 379 /// </summary> 380 SingleStreamNest, 381 /// <summary> 382 /// multi-stream nest aggregation 383 /// </summary> 384 MultiStreamNest, 385 #endregion 386 387 /// <summary> 388 /// NotValid 389 /// </summary> 390 MaxMarker, 391 NotValid = MaxMarker 392 } 393 394 /// <summary> 395 /// Represents an operator 396 /// </summary> 397 internal abstract class Op 398 { 399 #region private state 400 private OpType m_opType; 401 #endregion 402 403 #region constructors 404 /// <summary> 405 /// Basic constructor 406 /// </summary> Op(OpType opType)407 internal Op(OpType opType) 408 { 409 m_opType = opType; 410 } 411 #endregion 412 413 #region public methods 414 /// <summary> 415 /// Represents an unknown arity. Usually for Ops that can have a varying number of Args 416 /// </summary> 417 internal const int ArityVarying = -1; 418 419 /// <summary> 420 /// Kind of Op 421 /// </summary> 422 internal OpType OpType { get { return m_opType; } } 423 424 /// <summary> 425 /// The Arity of this Op (ie) how many arguments can it have. 426 /// Returns -1 if the arity is not known a priori 427 /// </summary> 428 internal virtual int Arity { get { return ArityVarying; } } 429 430 /// <summary> 431 /// Is this a ScalarOp 432 /// </summary> 433 internal virtual bool IsScalarOp { get { return false; } } 434 435 /// <summary> 436 /// Is this a RulePatternOp 437 /// </summary> 438 internal virtual bool IsRulePatternOp { get { return false; } } 439 440 /// <summary> 441 /// Is this a RelOp 442 /// </summary> 443 internal virtual bool IsRelOp { get { return false; } } 444 445 /// <summary> 446 /// Is this an AncillaryOp 447 /// </summary> 448 internal virtual bool IsAncillaryOp { get { return false; } } 449 450 /// <summary> 451 /// Is this a PhysicalOp 452 /// </summary> 453 internal virtual bool IsPhysicalOp { get { return false; } } 454 455 /// <summary> 456 /// Is the other Op equivalent? 457 /// </summary> 458 /// <param name="other">the other Op to compare</param> 459 /// <returns>true, if the Ops are equivalent</returns> IsEquivalent(Op other)460 internal virtual bool IsEquivalent(Op other) 461 { 462 return false; 463 } 464 465 /// <summary> 466 /// Simple mechanism to get the type for an Op. Applies only to scalar and ancillaryOps 467 /// </summary> 468 internal virtual TypeUsage Type 469 { 470 get { return null; } 471 set { throw System.Data.Entity.Error.NotSupported(); } 472 } 473 474 /// <summary> 475 /// Visitor pattern method 476 /// </summary> 477 /// <param name="v">The BasicOpVisitor that is visiting this Op</param> 478 /// <param name="n">The Node that references this Op</param> 479 [DebuggerNonUserCode] Accept(BasicOpVisitor v, Node n)480 internal virtual void Accept(BasicOpVisitor v, Node n) 481 { 482 v.Visit(this, n); 483 } 484 485 /// <summary> 486 /// Visitor pattern method for visitors with a return value 487 /// </summary> 488 /// <param name="v">The visitor</param> 489 /// <param name="n">The node in question</param> 490 /// <returns>An instance of TResultType</returns> 491 [DebuggerNonUserCode] Accept(BasicOpVisitorOfT<TResultType> v, Node n)492 internal virtual TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) 493 { 494 return v.Visit(this, n); 495 } 496 #endregion 497 } 498 499 /// <summary> 500 /// All scalars fall into this category 501 /// </summary> 502 internal abstract class ScalarOp : Op 503 { 504 #region private state 505 private TypeUsage m_type; 506 #endregion 507 508 #region constructors 509 /// <summary> 510 /// Default constructor 511 /// </summary> 512 /// <param name="opType">kind of Op</param> 513 /// <param name="type">type of value produced by this Op</param> ScalarOp(OpType opType, TypeUsage type)514 internal ScalarOp(OpType opType, TypeUsage type) 515 : this(opType) 516 { 517 Debug.Assert(type != null, "No type specified for ScalarOp"); 518 m_type = type; 519 } 520 ScalarOp(OpType opType)521 protected ScalarOp(OpType opType) : base(opType) { } 522 #endregion 523 524 #region public methods 525 /// <summary> 526 /// ScalarOp 527 /// </summary> 528 internal override bool IsScalarOp { get { return true; } } 529 530 /// <summary> 531 /// Two scalarOps are equivalent (usually) if their OpTypes and types are the 532 /// same. Obviously, their arguments need to be equivalent as well - but that's 533 /// checked elsewhere 534 /// </summary> 535 /// <param name="other">The other Op to compare against</param> 536 /// <returns>true, if the Ops are indeed equivalent</returns> IsEquivalent(Op other)537 internal override bool IsEquivalent(Op other) 538 { 539 return (other.OpType == this.OpType && TypeSemantics.IsStructurallyEqual(this.Type, other.Type)); 540 } 541 542 /// <summary> 543 /// Datatype of result 544 /// </summary> 545 internal override TypeUsage Type 546 { 547 get { return m_type; } 548 set { m_type = value; } 549 } 550 551 /// <summary> 552 /// Is this an Aggregate 553 /// </summary> 554 internal virtual bool IsAggregateOp 555 { 556 get{return false;} 557 } 558 #endregion 559 } 560 561 /// <summary> 562 /// All relational operators - filter, project, join etc. 563 /// </summary> 564 internal abstract class RelOp : Op 565 { 566 #region constructors 567 /// <summary> 568 /// Basic constructor. 569 /// </summary> 570 /// <param name="opType">kind of Op</param> RelOp(OpType opType)571 internal RelOp(OpType opType) : base(opType) { } 572 #endregion 573 574 #region public methods 575 /// <summary> 576 /// RelOp 577 /// </summary> 578 internal override bool IsRelOp { get { return true; } } 579 #endregion 580 } 581 582 /// <summary> 583 /// AncillaryOp 584 /// </summary> 585 internal abstract class AncillaryOp : Op 586 { 587 #region constructors 588 /// <summary> 589 /// Default constructor 590 /// </summary> 591 /// <param name="opType">kind of Op</param> AncillaryOp(OpType opType)592 internal AncillaryOp(OpType opType) : base(opType) { } 593 #endregion 594 595 #region public methods 596 /// <summary> 597 /// AncillaryOp 598 /// </summary> 599 internal override bool IsAncillaryOp { get { return true; } } 600 #endregion 601 } 602 603 /// <summary> 604 /// Represents all physical operators 605 /// </summary> 606 internal abstract class PhysicalOp : Op 607 { 608 #region constructors 609 /// <summary> 610 /// Default constructor 611 /// </summary> 612 /// <param name="opType">the op type</param> PhysicalOp(OpType opType)613 internal PhysicalOp(OpType opType) : base(opType) { } 614 #endregion 615 616 #region public methods 617 /// <summary> 618 /// This is a physical Op 619 /// </summary> 620 internal override bool IsPhysicalOp { get { return true; } } 621 #endregion 622 } 623 624 /// <summary> 625 /// All rule pattern operators - Leaf, Tree 626 /// </summary> 627 internal abstract class RulePatternOp : Op 628 { 629 #region constructors 630 /// <summary> 631 /// Default constructor 632 /// </summary> 633 /// <param name="opType">kind of Op</param> RulePatternOp(OpType opType)634 internal RulePatternOp(OpType opType) : base(opType) { } 635 #endregion 636 637 #region public methods 638 /// <summary> 639 /// RulePatternOp 640 /// </summary> 641 internal override bool IsRulePatternOp { get { return true; } } 642 #endregion 643 } 644 } 645