protected internal override Node VisitSelectFromStatement(SelectFromStatement node)
        {
            node = (SelectFromStatement)base.VisitSelectFromStatement(node);

            if (node.Groupings.Any())
            {
                var groupQuery     = GroupQueryVisitor.GetGroupQuery(node, this.data);
                var groupFactories = this.GetGroupValueFactory(groupQuery.Expressions.Concat(new[]
                {
                    new AliasedSqlExpression(groupQuery.Having, "$having"),
                }).Concat(groupQuery.OrderBy.Select((o, i) => new AliasedSqlExpression(o.Expression, $"$order{i}"))).Where(e => e.Expression != null));
                var plan   = this.CreateSelectQueryPlan(groupQuery.RowSelect);
                var fields = node.Expressions.Select(f => f.Expression is WildcardSqlExpression ? "*" : f.Alias);
                var orders = groupQuery.OrderBy.Select((o, i) => new OrderByExpression(CustomExpression.MakeSourceField(null, $"$order{i}", true), o.Ascending));
                var having = groupQuery.Having == null ? null : CustomExpression.MakeSourceField(null, "$having", true, typeof(bool));

                var aliases = groupQuery.Expressions;

                this.data.SetQueryPlan(node, new SelectGroupByQueryPlan(plan, groupFactories, groupQuery.Groupings, aliases, having, orders, fields));
            }
            else
            {
                this.data.SetQueryPlan(node, this.CreateSelectQueryPlan(node));
            }

            return(node);
        }
        public static IGroupQuery GetGroupQuery(SelectFromStatement select, INodeDataProvider data)
        {
            var visitor = new GroupQueryVisitor(select, data);

            return(new GroupQuery(visitor.Visit(select), visitor.Expressions, visitor.Groupings, visitor.Having, visitor.OrderBy));
        }