/// <summary>
            /// The from clause can contain top level concat operators as well.
            /// </summary>
            /// <param name="fromClause"></param>
            /// <param name="queryModel"></param>
            public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
            {
                bool processed = false;

                if (fromClause.FromExpression is SubQueryExpression)
                {
                    var sq = fromClause.FromExpression as SubQueryExpression;
                    var qms = Split(sq.QueryModel);
                    if (qms.Length > 1)
                    {
                        processed = true;

                        // Find which Result operators we should remove for all but the last item.
                        var lastConcat = queryModel.ResultOperators.Reverse().Where(x => x is ConcatResultOperator).FirstOrDefault();
                        int? lastConcatIndex = lastConcat == null ? (int?) null : queryModel.ResultOperators.IndexOf(lastConcat);

                        // Create a new one for each from expression, and substitute in for the current one.
                        // Recursively process it.
                        foreach (var qSub in qms)
                        {
                            var qm = queryModel.Clone();
                            qm.MainFromClause.FromExpression = new SubQueryExpression(qSub);
                            qm.Flatten();

                            if (lastConcatIndex.HasValue && qSub != qms[qms.Length - 1])
                            {
                                for (int i = 0; i < lastConcatIndex + 1; i++)
                                {
                                    qm.ResultOperators.RemoveAt(0);
                                }
                            }

                            VisitQueryModel(qm);
                        }
                    }
                }

                if (!processed)
                {
                    base.VisitMainFromClause(fromClause, queryModel);

                    // Models that don't need further processing are "done".
                    _models.Add(queryModel);
                }
            }
            /// <summary>
            /// Given a query model, look at all the result operators for Concat operators, and split everything up
            /// into separate query models.
            /// </summary>
            /// <param name="queryModel"></param>
            /// <returns></returns>
            private static IEnumerable<QueryModel> SplitQMByConcatResultOperator(QueryModel queryModel)
            {
                // If there are no concat result operators in the list, then we just bail quickly.
                // This is to specifically avoid the Clone operation unless we actually need it.
                if (!queryModel.ResultOperators.Where(r => r is ConcatResultOperator).Any())
                {
                    return new QueryModel[] { queryModel };
                }

                // Now, look for concat operators in the list. Pop them out when we find them.
                ConcatResultOperator ro = null;
                var qm = queryModel.Clone();
                var lst = new List<QueryModel>();
                while ((ro = qm.ResultOperators.Reverse().Where(r => r is ConcatResultOperator).Cast<ConcatResultOperator>().FirstOrDefault()) != null)
                {
                    // We are going to make q QueryModel here that uses the second source in the Concat operator.
                    // This means everything that comes before this query can be ignored - and we want this "source" to
                    // become the query from clause. Note this also means messing with the "select" clause to make sure it
                    // isn't doing anything special (select clause comes before result operators, semantically).

                    QueryModel newQM = NewQMFromOldWithLifting(ro.Source2, qm.MainFromClause.ItemType, qm.MainFromClause.ItemName);

                    var cc = new CloneContext(new QuerySourceMapping());

                    var indexToRemoveTo = qm.ResultOperators.IndexOf(ro);
                    for (int i = indexToRemoveTo + 1; i < qm.ResultOperators.Count; i++)
                    {
                        newQM.ResultOperators.Add(qm.ResultOperators[i].Clone(cc));
                    }
                    lst.Add(newQM.Flatten());

                    // Ok - we've taken one branch. We need to remove it from the list of things to look at, and work on the
                    // next one.
                    qm.ResultOperators.Remove(ro);
                }

                // The QueryModel left over needs to be added to the list.
                lst.Add(qm.Flatten());
                return lst;
            }