File: System\Data\Query\InternalTrees\RelOps.cs
Project: ndp\fx\src\DataEntity\System.Data.Entity.csproj (System.Data.Entity)
//---------------------------------------------------------------------
// <copyright file="RelOps.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner  Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
 
using System;
using System.Collections.Generic;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Globalization;
using System.Text;
 
namespace System.Data.Query.InternalTrees
{
    internal abstract class ScanTableBaseOp : RelOp
    {
        #region private state
        private Table m_table;
        #endregion
 
        #region constructors
        protected ScanTableBaseOp(OpType opType, Table table)
            : base(opType)
        {
            m_table = table;
        }
        protected ScanTableBaseOp(OpType opType)
            : base(opType)
        { }
        #endregion
 
        #region public methods
        /// <summary>
        /// Get the table instance produced by this Op
        /// </summary>
        internal Table Table { get { return m_table; } }
        #endregion
    }
 
    /// <summary>
    /// Scans a table
    /// </summary>
    internal sealed class ScanTableOp : ScanTableBaseOp
    {
        #region constructors
        /// <summary>
        /// Scan constructor
        /// </summary>
        /// <param name="table"></param>
        internal ScanTableOp(Table table)
            : base(OpType.ScanTable, table)
        {
        }
 
        private ScanTableOp() : base(OpType.ScanTable) { }
#endregion
 
        #region public methods
        /// <summary>
        /// Only to be used for pattern matches
        /// </summary>
        internal static readonly ScanTableOp Pattern = new ScanTableOp();
 
        /// <summary>
        /// No children
        /// </summary>
        internal override int Arity {get {return 0;} }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
#endregion
    }
 
    /// <summary>
    /// Scans a view - very similar to a ScanTable
    /// </summary>
    internal sealed class ScanViewOp : ScanTableBaseOp
    {
        #region constructors
        /// <summary>
        /// Scan constructor
        /// </summary>
        /// <param name="table"></param>
        internal ScanViewOp(Table table)
            : base(OpType.ScanView, table)
        {
        }
        private ScanViewOp() : base(OpType.ScanView) { }
#endregion
 
        #region public methods
        /// <summary>
        /// Only to be used for pattern matches
        /// </summary>
        internal static readonly ScanViewOp Pattern = new ScanViewOp();
 
        /// <summary>
        /// Exactly 1 child
        /// </summary>
        internal override int Arity { get { return 1; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// Scans a virtual extent (ie) a transient collection
    /// </summary>
    internal sealed class UnnestOp : RelOp
    {
        #region private state
        private Table m_table;
        private Var m_var;
        #endregion
 
        #region constructors
        internal UnnestOp(Var v, Table t) : this()
        {
            m_var = v;
            m_table = t;
        }
        private UnnestOp()
            : base(OpType.Unnest)
        {
        }
#endregion
 
        #region publics
        internal static readonly UnnestOp Pattern = new UnnestOp();
 
        /// <summary>
        /// The (collection-typed) Var that's being unnested
        /// </summary>
        internal Var Var { get { return m_var; } }
 
        /// <summary>
        /// The table instance produced by this Op
        /// </summary>
        internal Table Table { get { return m_table; } }
 
        /// <summary>
        /// Exactly 1 child
        /// </summary>
        internal override int Arity { get { return 1; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// Base class for all Join operations
    /// </summary>
    internal abstract class JoinBaseOp : RelOp
    {
        #region constructors
        internal JoinBaseOp(OpType opType) : base(opType) { }
        #endregion
 
        #region public surface
        /// <summary>
        /// 3 children - left, right, pred
        /// </summary>
        internal override int Arity { get { return 3; } }
        #endregion
    }
 
    /// <summary>
    /// A CrossJoin (n-way)
    /// </summary>
    internal sealed class CrossJoinOp : JoinBaseOp
    {
        #region constructors
        private CrossJoinOp() : base(OpType.CrossJoin) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// Singleton instance
        /// </summary>
        internal static readonly CrossJoinOp Instance = new CrossJoinOp();
        internal static readonly CrossJoinOp Pattern = CrossJoinOp.Instance;
 
        /// <summary>
        /// varying number of children (but usually greater than 1)
        /// </summary>
        internal override int Arity { get { return ArityVarying; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// An InnerJoin
    /// </summary>
    internal sealed class InnerJoinOp : JoinBaseOp
    {
        #region constructors
        private InnerJoinOp() : base(OpType.InnerJoin) { }
        #endregion
 
        #region public methods
        internal static readonly InnerJoinOp Instance = new InnerJoinOp();
        internal static readonly InnerJoinOp Pattern = InnerJoinOp.Instance;
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// A LeftOuterJoin
    /// </summary>
    internal sealed class LeftOuterJoinOp : JoinBaseOp
    {
        #region constructors
        private LeftOuterJoinOp() : base(OpType.LeftOuterJoin) { }
        #endregion
 
        #region public methods
        internal static readonly LeftOuterJoinOp Instance = new LeftOuterJoinOp();
        internal static readonly LeftOuterJoinOp Pattern = LeftOuterJoinOp.Instance;
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// A FullOuterJoin
    /// </summary>
    internal sealed class FullOuterJoinOp : JoinBaseOp
    {
        #region private constructors
        private FullOuterJoinOp() : base(OpType.FullOuterJoin) { }
        #endregion
 
        #region public methods
        internal static readonly FullOuterJoinOp Instance = new FullOuterJoinOp();
        internal static readonly FullOuterJoinOp Pattern = FullOuterJoinOp.Instance;
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// Base class for all Apply Ops
    /// </summary>
    internal abstract class ApplyBaseOp : RelOp
    {
        #region constructors
        internal ApplyBaseOp(OpType opType) : base(opType) { }
        #endregion
 
        #region public surface
        /// <summary>
        /// 2 children - left, right
        /// </summary>
        internal override int Arity { get { return 2; } }
        #endregion
    }
 
    /// <summary>
    /// CrossApply
    /// </summary>
    internal sealed class CrossApplyOp : ApplyBaseOp
    {
        #region constructors
        private CrossApplyOp() : base(OpType.CrossApply) { }
        #endregion
 
        #region public methods
        internal static readonly CrossApplyOp Instance = new CrossApplyOp();
        internal static readonly CrossApplyOp Pattern = CrossApplyOp.Instance;
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// OuterApply
    /// </summary>
    internal sealed class OuterApplyOp : ApplyBaseOp
    {
        #region constructors
        private OuterApplyOp() : base(OpType.OuterApply) { }
        #endregion
 
        #region public methods
        internal static readonly OuterApplyOp Instance = new OuterApplyOp();
        internal static readonly OuterApplyOp Pattern = OuterApplyOp.Instance;
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// FilterOp
    /// </summary>
    internal sealed class FilterOp : RelOp
    {
        #region constructors
        private FilterOp() : base(OpType.Filter) { }
        #endregion
 
        #region public methods
        internal static readonly FilterOp Instance = new FilterOp();
        internal static readonly FilterOp Pattern = FilterOp.Instance;
 
        /// <summary>
        /// 2 children - input, pred
        /// </summary>
        internal override int Arity { get { return 2; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// ProjectOp
    /// </summary>
    internal sealed class ProjectOp : RelOp
    {
        #region private state
        private VarVec m_vars;
        #endregion
 
        #region constructors
        private ProjectOp()
            : base(OpType.Project)
        { }
        internal ProjectOp(VarVec vars) : this()
        {
            Debug.Assert(null != vars, "null vars?");
            Debug.Assert(!vars.IsEmpty, "empty varlist?");
            m_vars = vars;
        }
        #endregion
 
        #region public methods
        internal static readonly ProjectOp Pattern = new ProjectOp();
 
        /// <summary>
        /// 2 children - input, projections (VarDefList)
        /// </summary>
        internal override int Arity { get { return 2; } }
 
        /// <summary>
        /// The Vars projected by this Op
        /// </summary>
        internal VarVec Outputs { get { return m_vars; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// A Sortkey
    /// </summary>
    internal class SortKey
    {
        #region private state
        private Var m_var;
        private bool m_asc;
        private string m_collation;
        #endregion
 
        #region constructors
        internal SortKey(Var v, bool asc, string collation)
        {
            m_var = v;
            m_asc = asc;
            m_collation = collation;
        }
        #endregion
 
        #region public methods
        /// <summary>
        /// The Var being sorted
        /// </summary>
        internal Var Var
        {
            get { return m_var; }
            set { m_var = value; }
        }
 
        /// <summary>
        /// Is this a sort asc, or a sort desc
        /// </summary>
        internal bool AscendingSort { get { return m_asc; } }
 
        /// <summary>
        /// An optional collation (only for string types)
        /// </summary>
        internal string Collation { get { return m_collation; } }
        #endregion
    }
 
    /// <summary>
    /// Base type for SortOp and ConstrainedSortOp
    /// </summary>
    internal abstract class SortBaseOp : RelOp
    {
        #region private state
        private List<SortKey> m_keys;
        #endregion
 
        #region Constructors
        // Pattern constructor
        internal SortBaseOp(OpType opType)
            : base(opType)
        {
            Debug.Assert(opType == OpType.Sort || opType == OpType.ConstrainedSort, "SortBaseOp OpType must be Sort or ConstrainedSort");
        }
 
        internal SortBaseOp(OpType opType, List<SortKey> sortKeys)
            : this(opType)
        {
            m_keys = sortKeys;
        }
 
        #endregion
 
        /// <summary>
        /// Sort keys
        /// </summary>
        internal List<SortKey> Keys { get { return m_keys; } }
    }
 
    /// <summary>
    /// A SortOp
    /// </summary>
    internal sealed class SortOp : SortBaseOp
    {
        #region constructors
        private SortOp() : base(OpType.Sort) { }
 
        internal SortOp(List<SortKey> sortKeys) : base(OpType.Sort, sortKeys) {}
        #endregion
 
        #region public methods
        internal static readonly SortOp Pattern = new SortOp();
 
        /// <summary>
        /// 1 child - the input, SortOp must not contain local VarDefs
        /// </summary>
        internal override int Arity { get { return 1; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// A Constrained SortOp. Used to represent physical paging (skip, limit, skip + limit) operations.
    /// </summary>
    internal sealed class ConstrainedSortOp : SortBaseOp
    {
        #region private state
        private bool _withTies;
        #endregion
 
        #region constructors
        // Pattern constructor
        private ConstrainedSortOp() : base(OpType.ConstrainedSort) { }
 
        internal ConstrainedSortOp(List<SortKey> sortKeys, bool withTies)
            : base(OpType.ConstrainedSort, sortKeys)
        {
            _withTies = withTies;
        }
        #endregion
 
        #region public methods
        internal bool WithTies { get { return _withTies; } set { _withTies = value; } }
 
        internal static readonly ConstrainedSortOp Pattern = new ConstrainedSortOp();
 
        /// <summary>
        /// 3 children - the input, a possibly NullOp limit and a possibly NullOp skip count.
        /// </summary>
        internal override int Arity { get { return 3; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// GroupByBaseOp
    /// </summary>
    internal abstract class GroupByBaseOp : RelOp
    {
        #region private state
        private VarVec m_keys;
        private VarVec m_outputs;
        #endregion
 
        #region constructors
        protected GroupByBaseOp(OpType opType) : base(opType) 
        {
            Debug.Assert(opType == OpType.GroupBy || opType == OpType.GroupByInto, "GroupByBaseOp OpType must be GroupBy or GroupByInto");
        }
        internal GroupByBaseOp(OpType opType, VarVec keys, VarVec outputs)
            : this(opType)
        {
            m_keys = keys;
            m_outputs = outputs;
        }
        #endregion
 
        #region public methods
        /// <summary>
        /// GroupBy keys
        /// </summary>
        internal VarVec Keys { get { return m_keys; } }
 
        /// <summary>
        /// All outputs of this Op - includes keys and aggregates
        /// </summary>
        internal VarVec Outputs { get { return m_outputs; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// GroupByOp
    /// </summary>
    internal sealed class GroupByOp : GroupByBaseOp
    {
        #region constructors
        private GroupByOp() : base(OpType.GroupBy) { }
        internal GroupByOp(VarVec keys, VarVec outputs)
            : base(OpType.GroupBy, keys, outputs)
        {
        }
        #endregion
 
        #region public methods
        internal static readonly GroupByOp Pattern = new GroupByOp();
 
        /// <summary>
        /// 3 children - input, keys (vardeflist), aggregates (vardeflist)
        /// </summary>
        internal override int Arity { get { return 3; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// GroupByIntoOp
    /// </summary>
    internal sealed class GroupByIntoOp : GroupByBaseOp
    {
        #region private state
        private readonly VarVec m_inputs;
        #endregion 
 
        #region constructors
        private GroupByIntoOp() : base(OpType.GroupByInto) { }
        internal GroupByIntoOp(VarVec keys, VarVec inputs, VarVec outputs)
            : base(OpType.GroupByInto, keys, outputs)
        {
            this.m_inputs = inputs;
        }
        #endregion
 
        #region public methods
        /// <summary>
        /// GroupBy keys
        /// </summary>
        internal VarVec Inputs { get { return m_inputs; } }
 
        internal static readonly GroupByIntoOp Pattern = new GroupByIntoOp();
 
        /// <summary>
        /// 4 children - input, keys (vardeflist), aggregates (vardeflist), groupaggregates (vardeflist)
        /// </summary>
        internal override int Arity { get { return 4; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// Base class for set operations - union, intersect, except
    /// </summary>
    internal abstract class SetOp : RelOp
    {
        #region private state
        private VarMap[] m_varMap;
        private VarVec m_outputVars;
        #endregion
 
        #region constructors
        internal SetOp(OpType opType, VarVec outputs, VarMap left, VarMap right)
            : this(opType)
        {
            m_varMap = new VarMap[2];
            m_varMap[0] = left;
            m_varMap[1] = right;
            m_outputVars = outputs;
        }
        protected SetOp(OpType opType) : base(opType)
        {
        }
        #endregion
 
        #region public methods
 
        /// <summary>
        /// 2 children - left, right
        /// </summary>
        internal override int Arity { get { return 2; } }
 
        /// <summary>
        /// Map of result vars to the vars of each branch of the setOp
        /// </summary>
        internal VarMap[] VarMap { get { return m_varMap; } }
 
        /// <summary>
        /// Get the set of output vars produced
        /// </summary>
        internal VarVec Outputs { get { return m_outputVars; } }
        #endregion
    }
 
    /// <summary>
    /// UnionAll (ie) no duplicate elimination
    /// </summary>
    internal sealed class UnionAllOp : SetOp
    {
        #region private state
        private Var m_branchDiscriminator;
        #endregion 
 
        #region constructors
        private UnionAllOp() : base(OpType.UnionAll) { }
 
        internal UnionAllOp(VarVec outputs, VarMap left, VarMap right, Var branchDiscriminator) : base(OpType.UnionAll, outputs, left, right) 
        { 
            m_branchDiscriminator = branchDiscriminator; 
        }
        #endregion
 
        #region public methods
        internal static readonly UnionAllOp Pattern = new UnionAllOp();
 
        /// <summary>
        /// Returns the branch discriminator var for this op.  It may be null, if
        /// we haven't been through key pullup yet.
        /// </summary>
        internal Var BranchDiscriminator { get { return m_branchDiscriminator; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// An IntersectOp
    /// </summary>
    internal sealed class IntersectOp : SetOp
    {
        #region constructors
        private IntersectOp() : base(OpType.Intersect) { }
        internal IntersectOp(VarVec outputs, VarMap left, VarMap right) : base(OpType.Intersect, outputs, left,right) { }
#endregion
 
        #region public methods
        internal static readonly IntersectOp Pattern = new IntersectOp();
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// ExceptOp (Minus)
    /// </summary>
    internal sealed class ExceptOp : SetOp
    {
        #region constructors
        private ExceptOp() : base(OpType.Except) { }
        internal ExceptOp(VarVec outputs, VarMap left, VarMap right) : base(OpType.Except, outputs, left, right) { }
        #endregion
 
        #region public methods
        internal static readonly ExceptOp Pattern = new ExceptOp();
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// DistinctOp
    /// </summary>
    internal sealed class DistinctOp : RelOp
    {
        #region private state
        private VarVec m_keys;
        #endregion
 
        #region constructors
        private DistinctOp() : base(OpType.Distinct)
        {
        }
        internal DistinctOp(VarVec keyVars) : this()
        {
            Debug.Assert(keyVars != null);
            Debug.Assert(!keyVars.IsEmpty);
            m_keys = keyVars;
        }
        #endregion
 
        #region public methods
        internal static readonly DistinctOp Pattern = new DistinctOp();
 
        /// <summary>
        /// 1 child - input
        /// </summary>
        internal override int Arity { get { return 1; } }
 
        /// <summary>
        /// Get "key" vars for the distinct
        /// </summary>
        internal VarVec Keys { get { return m_keys; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
        #endregion
    }
 
    /// <summary>
    /// Selects out a single row from a underlying subquery. Two flavors of this Op exist.
    /// The first flavor enforces the single-row-ness (ie) an error is raised if the
    /// underlying subquery produces more than one row.
    /// The other flavor simply choses any row from the input
    /// </summary>
    internal sealed class SingleRowOp : RelOp
    {
        #region constructors
        private SingleRowOp() : base(OpType.SingleRow) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// Singleton instance
        /// </summary>
        internal static readonly SingleRowOp Instance = new SingleRowOp();
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly SingleRowOp Pattern = Instance;
 
        /// <summary>
        /// 1 child - input
        /// </summary>
        internal override int Arity { get { return 1; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
 
        #endregion
    }
 
    /// <summary>
    /// Represents a table with a single row
    /// </summary>
    internal sealed class SingleRowTableOp : RelOp
    {
        #region constructors
        private SingleRowTableOp() : base(OpType.SingleRowTable) { }
        #endregion
 
        #region public methods
        /// <summary>
        /// Singleton instance
        /// </summary>
        internal static readonly SingleRowTableOp Instance = new SingleRowTableOp();
        /// <summary>
        /// Pattern for transformation rules
        /// </summary>
        internal static readonly SingleRowTableOp Pattern = Instance;
 
        /// <summary>
        /// 0 children
        /// </summary>
        internal override int Arity { get { return 0; } }
 
        /// <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 override 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 override TResultType Accept<TResultType>(BasicOpVisitorOfT<TResultType> v, Node n) { return v.Visit(this, n); }
 
        #endregion
    }
 
}