Example #1
0
        private static List <string> GetIndexedFields(IndexDefinition definition, FieldNamesValidator fieldNamesValidator)
        {
            var fields = fieldNamesValidator.Fields.ToList();

            foreach (var spatialField in definition.Fields)
            {
                if (spatialField.Value.Spatial == null)
                {
                    continue;
                }
                if (spatialField.Value.Spatial.Strategy != Client.Documents.Indexes.Spatial.SpatialSearchStrategy.BoundingBox)
                {
                    continue;
                }

                fields.Remove(spatialField.Key);
                fields.AddRange(new[]
                {
                    spatialField.Key + "__minX",
                    spatialField.Key + "__minY",
                    spatialField.Key + "__maxX",
                    spatialField.Key + "__maxY",
                });
            }

            return(fields);
        }
Example #2
0
        private static List <StatementSyntax> HandleMap(string map, FieldNamesValidator fieldNamesValidator, MethodDetectorRewriter methodsDetector,
                                                        ref SyntaxList <MemberDeclarationSyntax> members)
        {
            try
            {
                map = NormalizeFunction(map);
                var expression = SyntaxFactory.ParseExpression(map).NormalizeWhitespace();

                fieldNamesValidator.Validate(map, expression);
                methodsDetector.Visit(expression);

                var queryExpression = expression as QueryExpressionSyntax;
                if (queryExpression != null)
                {
                    return(HandleSyntaxInMap(fieldNamesValidator, new MapFunctionProcessor(CollectionNameRetriever.QuerySyntax, SelectManyRewriter.QuerySyntax), queryExpression, ref members));
                }
                var invocationExpression = expression as InvocationExpressionSyntax;
                if (invocationExpression != null)
                {
                    return(HandleSyntaxInMap(fieldNamesValidator, new MapFunctionProcessor(CollectionNameRetriever.MethodSyntax, SelectManyRewriter.MethodSyntax), invocationExpression, ref members));
                }

                throw new InvalidOperationException("Not supported expression type.");
            }
            catch (Exception ex)
            {
                throw new IndexCompilationException(ex.Message, ex)
                      {
                          IndexDefinitionProperty = nameof(IndexDefinition.Maps),
                          ProblematicText         = map
                      };
            }
        }
Example #3
0
        public RavenLinqOptimizer(FieldNamesValidator validator)
        {
            if (validator.Fields == null || validator.Fields.Length == 0)
            {
                throw new InvalidOperationException("Validator should have been validating original indexing func");
            }

            _validator = validator;
        }
Example #4
0
        private static StatementSyntax HandleReduce(string reduce, FieldNamesValidator fieldNamesValidator, MethodDetectorRewriter methodsDetector, out string[] groupByFields)
        {
            try
            {
                reduce = NormalizeFunction(reduce);
                var expression = SyntaxFactory.ParseExpression(reduce).NormalizeWhitespace();
                fieldNamesValidator?.Validate(reduce, expression);
                methodsDetector.Visit(expression);

                StatementSyntax result;

                switch (expression)
                {
                case QueryExpressionSyntax queryExpression:
                    result = HandleSyntaxInReduce(
                        new ReduceFunctionProcessor(
                            ResultsVariableNameRewriter.QuerySyntax,
                            GroupByFieldsRetriever.QuerySyntax,
                            SelectManyRewriter.QuerySyntax),
                        MethodsInGroupByValidator.QuerySyntaxValidator,
                        queryExpression, out groupByFields);
                    break;

                case InvocationExpressionSyntax invocationExpression:
                    result = HandleSyntaxInReduce(
                        new ReduceFunctionProcessor(
                            ResultsVariableNameRewriter.MethodSyntax,
                            GroupByFieldsRetriever.MethodSyntax,
                            SelectManyRewriter.MethodSyntax),
                        MethodsInGroupByValidator.MethodSyntaxValidator,
                        invocationExpression, out groupByFields);
                    break;

                default:
                    throw new InvalidOperationException("Not supported expression type.");
                }

                foreach (var groupByField in groupByFields)
                {
                    if (fieldNamesValidator?.Fields.Contains(groupByField) == false)
                    {
                        throw new InvalidOperationException($"Group by field '{groupByField}' was not found on the list of index fields ({string.Join(", ",fieldNamesValidator.Fields)})");
                    }
                }

                return(result);
            }
            catch (Exception ex)
            {
                throw new IndexCompilationException(ex.Message, ex)
                      {
                          IndexDefinitionProperty = nameof(IndexDefinition.Reduce),
                          ProblematicText         = reduce
                      };
            }
        }
Example #5
0
        private static List <StatementSyntax> HandleSyntaxInMap(FieldNamesValidator fieldValidator, MapFunctionProcessor mapRewriter, ExpressionSyntax expression,
                                                                ref SyntaxList <MemberDeclarationSyntax> members)
        {
            var rewrittenExpression = (CSharpSyntaxNode)mapRewriter.Visit(expression);

            var optimized = new RavenLinqOptimizer(fieldValidator).Visit(new RavenLinqPrettifier().Visit(rewrittenExpression))
                            as StatementSyntax;

            var collectionName = string.IsNullOrWhiteSpace(mapRewriter.CollectionName) ? Constants.Documents.Collections.AllDocumentsCollection : mapRewriter.CollectionName;

            var collection = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(collectionName));
            var results    = new List <StatementSyntax>();

            if (optimized != null)
            {
                var method = SyntaxFactory.MethodDeclaration(SyntaxFactory.IdentifierName("IEnumerable"), SyntaxFactory.Identifier("Map_" + members.Count))
                             .WithParameterList(
                    SyntaxFactory.ParameterList(SyntaxFactory.SingletonSeparatedList(
                                                    SyntaxFactory.Parameter(SyntaxFactory.Identifier("docs"))
                                                    .WithType(
                                                        SyntaxFactory.GenericName("IEnumerable")
                                                        .WithTypeArgumentList(
                                                            SyntaxFactory.TypeArgumentList(
                                                                SyntaxFactory.SingletonSeparatedList <TypeSyntax>(SyntaxFactory.IdentifierName("dynamic"))
                                                                )
                                                            )
                                                        )
                                                    ))
                    )
                             .WithBody(SyntaxFactory.Block().AddStatements(optimized));

                members = members.Add(method);

                results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddMap)).Invoke(collection, RoslynHelper.This(method.Identifier.Text)).AsExpressionStatement()); // this.AddMap("Users", docs => from doc in docs ... )
            }
            else
            {
                var indexingFunction = SyntaxFactory.SimpleLambdaExpression(SyntaxFactory.Parameter(SyntaxFactory.Identifier("docs")), rewrittenExpression);

                results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddMap)).Invoke(collection, indexingFunction).AsExpressionStatement()); // this.AddMap("Users", docs => from doc in docs ... )
            }

            if (mapRewriter.ReferencedCollections != null)
            {
                foreach (var referencedCollection in mapRewriter.ReferencedCollections)
                {
                    var rc = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(referencedCollection));
                    results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddReferencedCollection)).Invoke(collection, rc).AsExpressionStatement());
                }
            }

            return(results);
        }
        private static SyntaxNode OptimizeExpression(string str)
        {
            var expression = SyntaxFactory.ParseExpression(str.Trim());
            var result     = new RavenLinqPrettifier().Visit(expression);

            var validator = new FieldNamesValidator();

            validator.Validate(str, SyntaxFactory.ParseExpression(str).NormalizeWhitespace());

            var expr = new RavenLinqOptimizer(validator).Visit(result);

            expr = expr.ReplaceTrivia(expr.DescendantTrivia(), (t1, t2) => new SyntaxTrivia());
            return(expr.NormalizeWhitespace());
        }
Example #7
0
        private static MemberDeclarationSyntax CreateClass(string name, IndexDefinition definition)
        {
            var statements          = new List <StatementSyntax>();
            var maps                = definition.Maps.ToList();
            var fieldNamesValidator = new FieldNamesValidator();
            var methodDetector      = new MethodDetectorRewriter();
            var members             = new SyntaxList <MemberDeclarationSyntax>();

            for (var i = 0; i < maps.Count; i++)
            {
                var map = maps[i];
                statements.AddRange(HandleMap(map, fieldNamesValidator, methodDetector, ref members));
            }

            if (string.IsNullOrWhiteSpace(definition.Reduce) == false)
            {
                statements.Add(HandleReduce(definition.Reduce, fieldNamesValidator, methodDetector, out string[] groupByFields));

                var groupByFieldsArray = GetArrayCreationExpression(groupByFields);
                statements.Add(RoslynHelper.This(nameof(StaticIndexBase.GroupByFields)).Assign(groupByFieldsArray).AsExpressionStatement());
            }

            var fields = GetIndexedFields(definition, fieldNamesValidator);

            var outputFieldsArray = GetArrayCreationExpression(fields);

            statements.Add(RoslynHelper.This(nameof(StaticIndexBase.OutputFields)).Assign(outputFieldsArray).AsExpressionStatement());

            var methods = methodDetector.Methods;

            if (methods.HasCreateField)
            {
                statements.Add(RoslynHelper.This(nameof(StaticIndexBase.HasDynamicFields)).Assign(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)).AsExpressionStatement());
            }

            if (methods.HasBoost)
            {
                statements.Add(RoslynHelper.This(nameof(StaticIndexBase.HasBoostedFields)).Assign(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)).AsExpressionStatement());
            }

            var ctor = RoslynHelper.PublicCtor(name)
                       .AddBodyStatements(statements.ToArray());


            return(RoslynHelper.PublicClass(name)
                   .WithBaseClass <StaticIndexBase>()
                   .WithMembers(members.Add(ctor)));
        }
Example #8
0
        private static StatementSyntax HandleReduce(string reduce, FieldNamesValidator fieldNamesValidator, MethodDetectorRewriter methodsDetector, out string[] groupByFields)
        {
            try
            {
                reduce = NormalizeFunction(reduce);
                var expression = SyntaxFactory.ParseExpression(reduce).NormalizeWhitespace();
                fieldNamesValidator?.Validate(reduce, expression);
                methodsDetector.Visit(expression);
                var queryExpression = expression as QueryExpressionSyntax;
                if (queryExpression != null)
                {
                    return
                        HandleSyntaxInReduce(
                            new ReduceFunctionProcessor(
                                ResultsVariableNameRewriter.QuerySyntax,
                                GroupByFieldsRetriever.QuerySyntax,
                                SelectManyRewriter.QuerySyntax),
                            MethodsInGroupByValidator.QuerySyntaxValidator,
                            queryExpression, out groupByFields);
                }

                var invocationExpression = expression as InvocationExpressionSyntax;
                if (invocationExpression != null)
                {
                    return
                        HandleSyntaxInReduce(
                            new ReduceFunctionProcessor(
                                ResultsVariableNameRewriter.MethodSyntax,
                                GroupByFieldsRetriever.MethodSyntax,
                                SelectManyRewriter.MethodSyntax),
                            MethodsInGroupByValidator.MethodSyntaxValidator,
                            invocationExpression, out groupByFields);
                }

                throw new InvalidOperationException("Not supported expression type.");
            }
            catch (Exception ex)
            {
                throw new IndexCompilationException(ex.Message, ex)
                {
                    IndexDefinitionProperty = nameof(IndexDefinition.Reduce),
                    ProblematicText = reduce
                };
            }
        }