Skip to content

Commit

Permalink
Use MAXRECURSION hint
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkMpn committed Sep 10, 2023
1 parent b2382e7 commit 95226dd
Showing 1 changed file with 45 additions and 10 deletions.
55 changes: 45 additions & 10 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlanBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,20 +285,55 @@ private void ConvertStatement(TSqlStatement statement, ExecutionPlanOptimizer op
JoinType = QualifiedJoinType.Inner,
};

if (cteValidator.RecursiveQueries.Count > 1)
{
// Combine the results of each recursive query with a concat node
var concat = new ConcatenateNode();
recurseLoop.RightSource = concat;

foreach (var qry in cteValidator.RecursiveQueries)
concat.Sources.Add(ConvertRecursiveCTEQuery(qry));
}
else
{
recurseLoop.RightSource = ConvertRecursiveCTEQuery(cteValidator.RecursiveQueries[0]);
}

// Ensure we don't get stuck in an infinite loop
var assert = new AssertNode
var maxRecursion = stmtWithCtes.OptimizerHints
.OfType<LiteralOptimizerHint>()
.Where(hint => hint.HintKind == OptimizerHintKind.MaxRecursion)
.FirstOrDefault()
?.Value
?.Value
?? "100";

if (!Int32.TryParse(maxRecursion, out var max) || max < 0)
throw new NotSupportedQueryFragmentException("Invalid MAXRECURSION hint", stmtWithCtes.OptimizerHints
.OfType<LiteralOptimizerHint>()
.Where(hint => hint.HintKind == OptimizerHintKind.MaxRecursion)
.First());

if (max > 0)
{
Source = recurseLoop,
Assertion = e =>
var assert = new AssertNode
{
var depth = e.GetAttributeValue<SqlInt32>(incrementedDepthField);
return depth.Value < 100;
},
ErrorMessage = "Recursion depth exceeded"
};
Source = recurseLoop,
Assertion = e =>
{
var depth = e.GetAttributeValue<SqlInt32>(incrementedDepthField);
return depth.Value < max;
},
ErrorMessage = "Recursion depth exceeded"
};

// Combine the recursion results into the main results
recurseConcat.Sources.Add(assert);
// Combine the recursion results into the main results
recurseConcat.Sources.Add(assert);
}
else
{
recurseConcat.Sources.Add(recurseLoop);
}

// TODO: Update the sources for each field in the concat node
recurseConcat.ColumnSet.Last().SourceColumns.Add(incrementedDepthField);
Expand Down

0 comments on commit 95226dd

Please sign in to comment.