/// <summary>
        /// Clones this <see cref="QueryModel"/>, returning a new <see cref="QueryModel"/> equivalent to this instance, but with its clauses being
        /// clones of this instance's clauses. Any <see cref="QuerySourceReferenceExpression"/> in the cloned clauses that points back to another clause
        /// in  this <see cref="QueryModel"/> (including its subqueries) is adjusted to point to the respective clones in the cloned
        /// <see cref="QueryModel"/>. Any subquery nested in the <see cref="QueryModel"/> is also cloned.
        /// </summary>
        /// <param name="querySourceMapping">The <see cref="QuerySourceMapping"/> defining how to adjust instances of
        /// <see cref="QuerySourceReferenceExpression"/> in the cloned <see cref="QueryModel"/>. If there is a <see cref="QuerySourceReferenceExpression"/>
        /// that points out of the <see cref="QueryModel"/> being cloned, specify its replacement via this parameter. At the end of the cloning process,
        /// this object maps all the clauses in this original <see cref="QueryModel"/> to the clones created in the process.
        /// </param>
        public QueryModel Clone(QuerySourceMapping querySourceMapping)
        {
            ArgumentUtility.CheckNotNull("querySourceMapping", querySourceMapping);

            var cloneContext      = new CloneContext(querySourceMapping);
            var queryModelBuilder = new QueryModelBuilder();

            queryModelBuilder.AddClause(MainFromClause.Clone(cloneContext));
            foreach (var bodyClause in BodyClauses)
            {
                queryModelBuilder.AddClause(bodyClause.Clone(cloneContext));
            }
            queryModelBuilder.AddClause(SelectClause.Clone(cloneContext));

            foreach (var resultOperator in ResultOperators)
            {
                var resultOperatorClone = resultOperator.Clone(cloneContext);
                queryModelBuilder.AddResultOperator(resultOperatorClone);
            }

            var clone = queryModelBuilder.Build();

            clone.TransformExpressions(ex => CloningExpressionTreeVisitor.AdjustExpressionAfterCloning(ex, cloneContext.QuerySourceMapping));
            clone.ResultTypeOverride = ResultTypeOverride;
            return(clone);
        }
    /// <summary>
    /// Clones this <see cref="QueryModel"/>, returning a new <see cref="QueryModel"/> equivalent to this instance, but with its clauses being
    /// clones of this instance's clauses. Any <see cref="QuerySourceReferenceExpression"/> in the cloned clauses that points back to another clause 
    /// in  this <see cref="QueryModel"/> (including its subqueries) is adjusted to point to the respective clones in the cloned 
    /// <see cref="QueryModel"/>. Any subquery nested in the <see cref="QueryModel"/> is also cloned.
    /// </summary>
    /// <param name="querySourceMapping">The <see cref="QuerySourceMapping"/> defining how to adjust instances of 
    /// <see cref="QuerySourceReferenceExpression"/> in the cloned <see cref="QueryModel"/>. If there is a <see cref="QuerySourceReferenceExpression"/>
    /// that points out of the <see cref="QueryModel"/> being cloned, specify its replacement via this parameter. At the end of the cloning process,
    /// this object maps all the clauses in this original <see cref="QueryModel"/> to the clones created in the process.
    /// </param>
    public QueryModel Clone (QuerySourceMapping querySourceMapping)
    {
      ArgumentUtility.CheckNotNull ("querySourceMapping", querySourceMapping);

      var cloneContext = new CloneContext (querySourceMapping);
      var queryModelBuilder = new QueryModelBuilder();

      queryModelBuilder.AddClause (MainFromClause.Clone (cloneContext));
      foreach (var bodyClause in BodyClauses)
        queryModelBuilder.AddClause (bodyClause.Clone (cloneContext));
      queryModelBuilder.AddClause (SelectClause.Clone (cloneContext));

      foreach (var resultOperator in ResultOperators)
      {
        var resultOperatorClone = resultOperator.Clone (cloneContext);
        queryModelBuilder.AddResultOperator (resultOperatorClone);
      }

      var clone = queryModelBuilder.Build ();
      clone.TransformExpressions (ex => CloningExpressionTreeVisitor.AdjustExpressionAfterCloning (ex, cloneContext.QuerySourceMapping));
      clone.ResultTypeOverride = ResultTypeOverride;
      return clone;
    }