internal static IEnumerable <IExpressionPart> GetFluxExpressions(Expression expression, object clause,
                                                                         QueryGenerationContext context)
        {
            Arguments.CheckNotNull(expression, nameof(expression));
            Arguments.CheckNotNull(clause, nameof(clause));
            Arguments.CheckNotNull(context, nameof(context));

            var visitor = new QueryExpressionTreeVisitor(clause, context);

            visitor.Visit(expression);
            return(visitor.GetFluxExpressions());
        }
        public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index)
        {
            base.VisitWhereClause(whereClause, queryModel, index);

            var expressions = GetExpressions(whereClause.Predicate, whereClause).ToList();

            var rangeFilter = new List <IExpressionPart>();
            var tagFilter   = new List <IExpressionPart>();
            var fieldFilter = new List <IExpressionPart>();

            // Map LINQ filter expresion to right place: range, tag filtering, field filtering
            foreach (var expression in expressions)
            {
                switch (expression)
                {
                // Range
                case TimeColumnName _:
                    rangeFilter.Add(expression);
                    break;

                // Tag
                case TagColumnName _:
                    tagFilter.Add(expression);
                    break;

                // Field
                case RecordColumnName _:
                    fieldFilter.Add(expression);
                    break;

                case NamedField _:
                    fieldFilter.Add(expression);
                    break;

                case NamedFieldValue _:
                    fieldFilter.Add(expression);
                    break;

                // Other expressions: binary operator, parenthesis
                default:
                    rangeFilter.Add(expression);
                    tagFilter.Add(expression);
                    fieldFilter.Add(expression);
                    break;
                }
            }

            QueryExpressionTreeVisitor.NormalizeExpressions(rangeFilter);
            QueryExpressionTreeVisitor.NormalizeExpressions(tagFilter);
            QueryExpressionTreeVisitor.NormalizeExpressions(fieldFilter);

            Debug.WriteLine("--- normalized LINQ expressions: ---");
            Debug.WriteLine($"range: {ConcatExpression(rangeFilter)}");
            Debug.WriteLine($"tag: {ConcatExpression(tagFilter)}");
            Debug.WriteLine($"field: {ConcatExpression(fieldFilter)}");

            // filter by time
            AddFilterByRange(rangeFilter);

            // filter by tags
            _context.QueryAggregator.AddFilterByTags(ConcatExpression(tagFilter));

            // filter by fields
            _context.QueryAggregator.AddFilterByFields(ConcatExpression(fieldFilter));
        }
 private IEnumerable <IExpressionPart> GetExpressions(Expression expression, object clause)
 {
     return(QueryExpressionTreeVisitor.GetFluxExpressions(expression, clause, _context));
 }