File: System\Data\Query\InternalTrees\Ops.cs
Project: ndp\fx\src\DataEntity\System.Data.Entity.csproj (System.Data.Entity)
//---------------------------------------------------------------------
// <copyright file="Ops.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner  Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
 
namespace System.Data.Query.InternalTrees
{
    using System.Data.Metadata.Edm;
    using System.Diagnostics;
 
    /// <summary>
    /// The operator types. Includes both scalar and relational operators, 
    /// and physical and logical operators, and rule operators 
    /// </summary>
    internal enum OpType
    {
        #region ScalarOpType
        /// <summary>
        /// Constants
        /// </summary>
        Constant,
 
        /// <summary>
        /// An internally generated constant
        /// </summary>
        InternalConstant,
 
        /// <summary>
        /// An internally generated constant used as a null sentinel
        /// </summary>
        NullSentinel,
 
        /// <summary>
        /// A null constant
        /// </summary>
        Null,
 
        /// <summary>
        /// ConstantPredicate
        /// </summary>
        ConstantPredicate,
        
        /// <summary>
        /// A Var reference
        /// </summary>
        VarRef,
 
        /// <summary>
        /// GreaterThan
        /// </summary>
        GT,
        
        /// <summary>
        /// >=
        /// </summary>
        GE,
        
        /// <summary>
        /// Lessthan or equals
        /// </summary>
        LE,
 
        /// <summary>
        /// Less than
        /// </summary>
        LT,
 
        /// <summary>
        /// Equals 
        /// </summary>
        EQ,
 
        /// <summary>
        /// Not equals
        /// </summary>
        NE,
 
        /// <summary>
        /// String comparison
        /// </summary>
        Like,
 
        /// <summary>
        /// Addition
        /// </summary>
        Plus,
 
        /// <summary>
        /// Subtraction
        /// </summary>
        Minus,
 
        /// <summary>
        /// Multiplication 
        /// </summary>
        Multiply,
 
        /// <summary>
        /// Division 
        /// </summary>
        Divide,
 
        /// <summary>
        /// Modulus 
        /// </summary>
        Modulo,
 
        /// <summary>
        /// Unary Minus 
        /// </summary>
        UnaryMinus,
 
        /// <summary>
        /// And 
        /// </summary>
        And,
 
        /// <summary>
        /// Or
        /// </summary>
        Or,
 
        /// <summary>
        /// Not
        /// </summary>
        Not,
        
        /// <summary>
        /// is null 
        /// </summary>
        IsNull,
 
        /// <summary>
        /// switched case expression
        /// </summary>
        Case,
 
        /// <summary>
        /// treat-as 
        /// </summary>
        Treat,
 
        /// <summary>
        /// is-of 
        /// </summary>
        IsOf,
 
        /// <summary>
        /// Cast
        /// </summary>
        Cast,
 
        /// <summary>
        /// Internal cast
        /// </summary>
        SoftCast,
 
        /// <summary>
        /// a basic aggregate
        /// </summary>
        Aggregate,
        
        /// <summary>
        /// function call
        /// </summary>
        Function,
 
        /// <summary>
        /// Reference to a "relationship" property
        /// </summary>
        RelProperty,
 
        /// <summary>
        /// property reference
        /// </summary>
        Property,
 
        /// <summary>
        /// entity constructor
        /// </summary>
        NewEntity,
 
        /// <summary>
        /// new instance constructor for a named type(other than multiset, record)
        /// </summary>
        NewInstance,
 
        /// <summary>
        /// new instance constructor for a named type and sub-types
        /// </summary>
        DiscriminatedNewEntity,
 
        /// <summary>
        /// Multiset constructor
        /// </summary>
        NewMultiset,
        
        /// <summary>
        /// record constructor
        /// </summary>
        NewRecord,
        
        /// <summary>
        /// Get the key from a Ref
        /// </summary>
        GetRefKey,
        
       /// <summary>
        /// Get the ref from an entity instance
        /// </summary>
        GetEntityRef,
        
        /// <summary>
        /// create a reference 
        /// </summary>
        Ref,
        
        /// <summary>
        /// exists
        /// </summary>
        Exists,
 
        /// <summary>
        /// get the singleton element from a collection
        /// </summary>
        Element,
 
        /// <summary>
        /// Builds up a collection
        /// </summary>
        Collect,
 
        /// <summary>
        /// gets the target entity pointed at by a reference
        /// </summary>
        Deref,
 
        /// <summary>
        /// Traverse a relationship and get the references of the other end
        /// </summary>
        Navigate,
        #endregion
 
        #region RelOpType
        /// <summary>
        /// A table scan
        /// </summary>
        ScanTable,
        /// <summary>
        /// A view scan
        /// </summary>
        ScanView,
 
        /// <summary>
        /// Filter
        /// </summary>
        Filter,
        
        /// <summary>
        /// Project
        /// </summary>
        Project,
 
        /// <summary>
        /// InnerJoin
        /// </summary>
        InnerJoin,
 
        /// <summary>
        /// LeftOuterJoin
        /// </summary>
        LeftOuterJoin,
 
        /// <summary>
        /// FullOuter join
        /// </summary>
        FullOuterJoin,
 
        /// <summary>
        /// Cross join
        /// </summary>
        CrossJoin,
 
        /// <summary>
        /// cross apply
        /// </summary>
        CrossApply,
 
        /// <summary>
        /// outer apply 
        /// </summary>
        OuterApply,
 
        /// <summary>
        /// Unnest
        /// </summary>
        Unnest,
 
        /// <summary>
        /// Sort
        /// </summary>
        Sort,
 
        /// <summary>
        /// Constrained Sort (physical paging - Limit and Skip)
        /// </summary>
        ConstrainedSort,
 
        /// <summary>
        /// GroupBy
        /// </summary>
        GroupBy,
 
        /// <summary>
        /// GroupByInto (projects the group as well)
        /// </summary>
        GroupByInto,
 
        /// <summary>
        /// UnionAll
        /// </summary>
        UnionAll,
        /// <summary>
        /// Intersect
        /// </summary>
        Intersect,
        /// <summary>
        /// Except
        /// </summary>
        Except,
 
        /// <summary>
        /// Distinct
        /// </summary>
        Distinct,
 
        /// <summary>
        /// Select a single row from a subquery
        /// </summary>
        SingleRow,
 
        /// <summary>
        /// A table with exactly one row
        /// </summary>
        SingleRowTable,
 
        #endregion
 
        #region AncillaryOpType
        /// <summary>
        /// Variable definition
        /// </summary>
        VarDef,
        /// <summary>
        /// List of variable definitions
        /// </summary>
        VarDefList,
        #endregion
        
        #region RulePatternOpType
        /// <summary>
        /// Leaf
        /// </summary>
        Leaf,
        #endregion
 
        #region PhysicalOpType
        /// <summary>
        /// Physical Project
        /// </summary>
        PhysicalProject,
 
        /// <summary>
        /// single-stream nest aggregation
        /// </summary>
        SingleStreamNest,
        /// <summary>
        /// multi-stream nest aggregation
        /// </summary>
        MultiStreamNest,
        #endregion
 
        /// <summary>
        /// NotValid
        /// </summary>
        MaxMarker,
        NotValid = MaxMarker
    }
 
    /// <summary>
    /// Represents an operator 
    /// </summary>
    internal abstract class Op
    {
        #region private state
        private OpType m_opType;
        #endregion
 
        #region constructors
        /// <summary>
        /// Basic constructor
        /// </summary>
        internal Op(OpType opType) 
        { 
            m_opType = opType; 
        }
        #endregion
 
        #region public methods
        /// <summary>
        /// Represents an unknown arity. Usually for Ops that can have a varying number of Args
        /// </summary>
        internal const int ArityVarying = -1;
 
        /// <summary>
        /// Kind of Op
        /// </summary>
        internal OpType OpType { get { return m_opType; } }
 
        /// <summary>
        /// The Arity of this Op (ie) how many arguments can it have.
        /// Returns -1 if the arity is not known a priori
        /// </summary>
        internal virtual int Arity { get { return ArityVarying; } }
 
        /// <summary>
        /// Is this a ScalarOp
        /// </summary>
        internal virtual bool IsScalarOp { get { return false; } }
 
        /// <summary>
        /// Is this a RulePatternOp
        /// </summary>
        internal virtual bool IsRulePatternOp { get { return false; } }
 
        /// <summary>
        /// Is this a RelOp
        /// </summary>
        internal virtual bool IsRelOp { get { return false; } }
 
        /// <summary>
        /// Is this an AncillaryOp
        /// </summary>
        internal virtual bool IsAncillaryOp { get { return false; } }
 
        /// <summary>
        /// Is this a PhysicalOp
        /// </summary>
        internal virtual bool IsPhysicalOp { get { return false; } }
 
        /// <summary>
        /// Is the other Op equivalent?
        /// </summary>
        /// <param name="other">the other Op to compare</param>
        /// <returns>true, if the Ops are equivalent</returns>
        internal virtual bool IsEquivalent(Op other)
        {
            return false;
        }
 
        /// <summary>
        /// Simple mechanism to get the type for an Op. Applies only to scalar and ancillaryOps
        /// </summary>
        internal virtual TypeUsage Type
        {
            get { return null; }
            set { throw System.Data.Entity.Error.NotSupported(); }
        }
 
        /// <summary>
        /// Visitor pattern method
        /// </summary>
        /// <param name="v">The BasicOpVisitor that is visiting this Op</param>
        /// <param name="n">The Node that references this Op</param>
        [DebuggerNonUserCode]
        internal virtual void Accept(BasicOpVisitor v, Node n) 
        { 
            v.Visit(this, n); 
        }
        
        /// <summary>
        /// Visitor pattern method for visitors with a return value
        /// </summary>
        /// <param name="v">The visitor</param>
        /// <param name="n">The node in question</param>
        /// <returns>An instance of TResultType</returns>
        [DebuggerNonUserCode]
        internal virtual TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) 
        { 
            return v.Visit(this, n);
        }
        #endregion
    }
 
    /// <summary>
    /// All scalars fall into this category
    /// </summary>
    internal abstract class ScalarOp : Op
    {
        #region private state
        private TypeUsage m_type;
        #endregion
 
        #region constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="opType">kind of Op</param>
        /// <param name="type">type of value produced by this Op</param>
        internal ScalarOp(OpType opType, TypeUsage type)
            : this(opType)
        {
            Debug.Assert(type != null, "No type specified for ScalarOp");
            m_type = type;
        }
 
        protected ScalarOp(OpType opType) : base(opType) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// ScalarOp
        /// </summary>
        internal override bool IsScalarOp { get { return true; } }
 
        /// <summary>
        /// Two scalarOps are equivalent (usually) if their OpTypes and types are the 
        /// same. Obviously, their arguments need to be equivalent as well - but that's
        /// checked elsewhere
        /// </summary>
        /// <param name="other">The other Op to compare against</param>
        /// <returns>true, if the Ops are indeed equivalent</returns>
        internal override bool IsEquivalent(Op other)
        {
            return (other.OpType == this.OpType && TypeSemantics.IsStructurallyEqual(this.Type, other.Type));
        }
 
        /// <summary>
        /// Datatype of result
        /// </summary>
        internal override TypeUsage Type 
        { 
            get { return m_type; } 
            set { m_type = value; } 
        }
        
        /// <summary>
        /// Is this an Aggregate
        /// </summary>
        internal virtual bool IsAggregateOp 
        {
            get{return false;}
        }
        #endregion
    }
 
    /// <summary>
    /// All relational operators - filter, project, join etc.
    /// </summary>
    internal abstract class RelOp : Op
    {
        #region constructors
        /// <summary>
        /// Basic constructor.
        /// </summary>
        /// <param name="opType">kind of Op</param>
        internal RelOp(OpType opType) : base(opType) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// RelOp
        /// </summary>
        internal override bool IsRelOp { get { return true; } }
        #endregion
    }
 
    /// <summary>
    /// AncillaryOp
    /// </summary>
    internal abstract class AncillaryOp : Op
    {
        #region constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="opType">kind of Op</param>
        internal AncillaryOp(OpType opType) : base(opType) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// AncillaryOp
        /// </summary>
        internal override bool IsAncillaryOp { get { return true; } }
        #endregion
    }
 
    /// <summary>
    /// Represents all physical operators
    /// </summary>
    internal abstract class PhysicalOp : Op
    {
        #region constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="opType">the op type</param>
        internal PhysicalOp(OpType opType) : base(opType) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// This is a physical Op
        /// </summary>
        internal override bool IsPhysicalOp { get { return true; } }
        #endregion
    }
 
    /// <summary>
    /// All rule pattern operators - Leaf, Tree
    /// </summary>
    internal abstract class RulePatternOp : Op
    {
        #region constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="opType">kind of Op</param>
        internal RulePatternOp(OpType opType) : base(opType) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// RulePatternOp
        /// </summary>
        internal override bool IsRulePatternOp { get { return true; } }
        #endregion
    }
}