/// <summary> /// Sort the current stream of the query. To do this we run through all the results, sort them, /// and then start a new loop. /// </summary> /// <param name="ordering"></param> /// <param name="queryModel"></param> /// <param name="orderByClause"></param> /// <param name="index"></param> public override void VisitOrdering(Ordering ordering, QueryModel queryModel, OrderByClause orderByClause, int index) { // // Only number types can be sorted. // if (!ordering.Expression.Type.IsNumberType()) { throw new InvalidOperationException(string.Format("Don't know how to sort query by type '{0}'.", ordering.Expression.Type.Name)); } // // First, record all the indicies and the values. This is what we are going to be sorting. // var mapRecord = DeclarableParameter.CreateDeclarableParameterMapExpression(ordering.Expression.Type, _codeContext.LoopIndexVariable.Type.MakeArrayType()); _codeEnv.AddOutsideLoop(mapRecord); var savePairValues = new StatementRecordPairValues(mapRecord, ExpressionToCPP.GetExpression(ordering.Expression, _codeEnv, _codeContext, MEFContainer), ExpressionToCPP.GetExpression(_codeContext.LoopIndexVariable.AsExpression(), _codeEnv, _codeContext, MEFContainer)); _codeEnv.Add(savePairValues); var otherSavers = _codeEnv.GetUsedQuerySourceVariables(savePairValues, _codeContext.LoopIndexVariable) .Select(v => { var mr = DeclarableParameter.CreateDeclarableParameterMapExpression(ordering.Expression.Type, v.Type.MakeArrayType()); _codeEnv.AddOutsideLoop(mr); savePairValues.AddSaver(mr, v); return(Tuple.Create(v, mr)); }) .ToArray(); // Get back to the results level now, where we do the sorting! _codeEnv.PopToResultsLevel(); // // Now, we need to sort and loop over the variables in the map. This is a bit of a messy // multi-line statement, and it is a compound statement. // var sortAndRunLoop = new StatementLoopOverSortedPairValue(mapRecord, ordering.OrderingDirection == OrderingDirection.Asc); _codeEnv.Add(sortAndRunLoop); var pindex = sortAndRunLoop.IndexVariable; var lv = _codeContext.LoopIndexVariable.RawValue; _codeContext.Add(lv, pindex); foreach (var savers in otherSavers) { var newVarName = sortAndRunLoop.RestoreOtherSaver(savers.Item2); _codeContext.Add(savers.Item1.RawValue, newVarName); } _codeContext.SetLoopVariable(_codeContext.LoopVariable.ReplaceSubExpression(_codeContext.LoopIndexVariable.AsExpression(), pindex), pindex); }