private IGraphQueryStep BuildQueryPlanForPattern(PatternMatchElementExpression patternExpression, int start) { var prev = BuildQueryPlanForMatchNode(patternExpression.Path[start]); for (int i = start + 1; i < patternExpression.Path.Length; i += 2) { if (patternExpression.Path[i].Recursive == null) { var next = i + 1 < patternExpression.Path.Length ? BuildQueryPlanForMatchNode(patternExpression.Path[i + 1]) : null; prev = BuildQueryPlanForEdge(prev, next, patternExpression.Path[i]); } else { return(BuildQueryPlanForRecursiveEdge(prev, i, patternExpression)); } } return(prev); }
private IGraphQueryStep BuildQueryPlanForRecursiveEdge(IGraphQueryStep left, int index, PatternMatchElementExpression patternExpression) { var recursive = patternExpression.Path[index].Recursive.Value; var pattern = recursive.Pattern; var steps = new List <SingleEdgeMatcher>((pattern.Count + 1) / 2); for (int i = 0; i < pattern.Count; i += 2) { if (GraphQuery.WithEdgePredicates.TryGetValue(pattern[i].Alias, out var recursiveEdge) == false) { throw new InvalidOperationException($"BuildQueryPlanForEdge was invoked for recursive alias='{pattern[i].Alias}' which suppose to be an edge but no corresponding WITH EDGE clause was found."); } steps.Add(new SingleEdgeMatcher { IncludedEdges = new Dictionary <string, Sparrow.Json.BlittableJsonReaderObject>(StringComparer.OrdinalIgnoreCase), QueryParameters = _query.QueryParameters, Edge = recursiveEdge, Results = new List <Match>(), Right = i + 1 < pattern.Count ? BuildQueryPlanForMatchNode(pattern[i + 1]) : null, EdgeAlias = pattern[i].Alias }); } var recursiveStep = new RecursionQueryStep(left, steps, recursive, recursive.GetOptions(_query.Metadata, _query.QueryParameters), _token) { CollectIntermediateResults = CollectIntermediateResults }; if (index + 1 < patternExpression.Path.Length) { if (patternExpression.Path[index + 1].Recursive.HasValue) { throw new InvalidQueryException("Two adjacent 'recursive' queries are not allowed", GraphQuery.QueryText); } if (patternExpression.Path[index + 1].IsEdge) { var nextPlan = BuildQueryPlanForPattern(patternExpression, index + 2); nextPlan = BuildQueryPlanForEdge(recursiveStep, nextPlan, patternExpression.Path[index + 1]); recursiveStep.SetNext(nextPlan.GetSingleGraphStepExecution()); } else { var nextPlan = BuildQueryPlanForPattern(patternExpression, index + 1); recursiveStep.SetNext(nextPlan.GetSingleGraphStepExecution()); } } return(recursiveStep); }