Exemple #1
0
        /// <summary>
        /// Process the grouping operator. We have to sort through the items, group them, and then
        /// create an object we can be translated later to access the items or the Key. We need to return
        /// an IEnumerable<IGrouping<TKey, TElement>>... As a result, this is one of those operators that has
        /// a fair amount of implementation in other parts of the re-linq structure.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        /// <remarks>
        /// re-linq blog post that shows the format of the query we are dealing with: https://www.re-motion.org/blogs/mix/2009/09/01/re-linq-how-to-support-ldquogroup-intordquo-with-aggregates
        /// Not as useful:
        /// Code for the result operator (including in-memory execution): https://svn.re-motion.org/svn/Remotion/trunk/Relinq/Core/Clauses/ResultOperators/GroupResultOperator.cs
        /// Unit tests for the result operator: https://www.re-motion.org/fisheye/browse/~raw,r=17871/Remotion/trunk/Remotion/Data/Linq.UnitTests/Linq/SqlBackend/SqlPreparation/ResultOperatorHandlers/GroupResultOperatorHandlerTest.cs
        /// </remarks>
        System.Linq.Expressions.Expression IQVScalarResultOperator.ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            //
            // Basic checks
            //

            var groupOp = resultOperator as GroupResultOperator;

            if (groupOp == null)
            {
                throw new ArgumentNullException("resultOperator");
            }

            if (!groupOp.KeySelector.Type.IsNumberType())
            {
                throw new InvalidOperationException(string.Format("Don't know how to group by type '{0}'.", groupOp.KeySelector.Type.Name));
            }

            //
            // First, record all the indicies and the values. This is what we are going to be grouping.
            //

            var mapRecord = DeclarableParameter.CreateDeclarableParameterMapExpression(groupOp.KeySelector.Type, typeof(int).MakeArrayType());

            gc.AddOutsideLoop(mapRecord);

            var savePairValues = new StatementRecordPairValues(mapRecord,
                                                               ExpressionToCPP.GetExpression(groupOp.KeySelector, gc, cc, container),
                                                               ExpressionToCPP.GetExpression(cc.LoopIndexVariable.AsExpression(), gc, cc, container));

            gc.Add(savePairValues);

            gc.Pop();

            //
            // Now create the object that will be handed back for later parsing. This should contain the info that is needed to do the
            // actual looping over the groups when it is requested.
            //

            var t_return = typeof(GroupByTypeTagEnum <int, int>).GetGenericTypeDefinition().MakeGenericType(new Type[] { groupOp.KeySelector.Type, groupOp.ElementSelector.Type });
            var ctor     = t_return.GetConstructor(new Type[] { });
            var o        = ctor.Invoke(new object[] { }) as BaseGroupInfo;

            o.MapRecord                    = mapRecord;
            o.TargetExpression             = groupOp.ElementSelector;
            o.TargetExpressionLoopVariable = cc.LoopIndexVariable;

            return(Expression.Constant(o, t_return));
        }
        /// <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);
        }
Exemple #3
0
        public void CreateDeclarableParameterMapExpressionTest()
        {
            var r = DeclarableParameter.CreateDeclarableParameterMapExpression(typeof(int), typeof(double));

            Assert.AreEqual(typeof(Dictionary <int, double>), r.Type, "map type not right");
        }