/// <summary>
        /// If some node has no dependency, we will take it into consideration
        /// </summary>
        /// <param name="aggregationBlock"></param>
        /// <param name="predicateLinksAccessedTableAliases"></param>
        /// <returns></returns>
        public List <ExecutionOrder> GenerateNextOrders(
            AggregationBlock aggregationBlock,
            List <Tuple <PredicateLink, HashSet <string> > > predicateLinksAccessedTableAliases)
        {
            // Find all possible next tuples
            List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > > nextTuples =
                new List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > >();

            foreach (KeyValuePair <string, HashSet <string> > pair in aggregationBlock.TableInputDependency)
            {
                if (!this.ExistingNodesAndEdges.Contains(pair.Key) && this.ExistingNodesAndEdges.IsSupersetOf(pair.Value))
                {
                    CompileNode node;
                    aggregationBlock.TryGetNode(pair.Key, out node);
                    nextTuples.AddRange(this.GenerateTuples(predicateLinksAccessedTableAliases, node));
                }
            }

            // Generate all possible next orders
            List <ExecutionOrder> nextOrders = new List <ExecutionOrder>();

            foreach (Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > tuple in nextTuples)
            {
                ExecutionOrder nextOrder = this.Duplicate();
                nextOrder.AddTuple(tuple);
                nextOrders.Add(nextOrder);
            }
            return(nextOrders);
        }
        /// <summary>
        /// The AggregationTable maybe a side-effect table or other special table, so it need to handle firstly.
        /// </summary>
        /// <param name="aggregationBlock"></param>
        /// <param name="predicateLinksAccessedTableAliases"></param>
        public void AddRootTable(
            AggregationBlock aggregationBlock,
            List <Tuple <PredicateLink, HashSet <string> > > predicateLinksAccessedTableAliases)
        {
            NonFreeTable rootTable = aggregationBlock.NonFreeTables[aggregationBlock.RootTableAlias];

            // Find local execution orders
            List <ExecutionOrder> localExecutionOrders = rootTable.GetLocalExecutionOrder(this).Order.First().Item5;

            // Find connected predicateLinks
            List <Tuple <PredicateLink, int> > forwardLinks;
            List <Tuple <MatchEdge, int> >     backwardEdges = new List <Tuple <MatchEdge, int> >();

            // Find predicates that can be evaluated
            forwardLinks = this.FindPredicates(rootTable, null, backwardEdges, predicateLinksAccessedTableAliases);
            // Add a next possible tuple
            this.AddTuple(
                new Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> >(
                    rootTable, null, forwardLinks, backwardEdges, localExecutionOrders));
        }