public void HandleResultOperator () { var keySelector = new SqlColumnDefinitionExpression(typeof(string), "c", "Name", false); var elementSelector = Expression.Constant ("elementSelector"); var resultOperator = new GroupResultOperator ("itemName", keySelector, elementSelector); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (keySelector, _context)) .Return (keySelector); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (elementSelector, _context)) .Return (elementSelector); _stageMock.Replay(); _handler.HandleResultOperator (resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations(); Assert.That (_sqlStatementBuilder.GroupByExpression, Is.SameAs (keySelector)); var expectedSelectProjection = new SqlGroupingSelectExpression ( new NamedExpression ("key", keySelector), new NamedExpression ("element", elementSelector)); SqlExpressionTreeComparer.CheckAreEqualTrees (expectedSelectProjection, _sqlStatementBuilder.SelectProjection); Assert.That ( _sqlStatementBuilder.DataInfo.DataType, Is.EqualTo (typeof (IQueryable<>).MakeGenericType (typeof (IGrouping<,>).MakeGenericType (typeof (string), typeof (string))))); }
public void HandleResultOperator() { var keySelector = new SqlColumnDefinitionExpression(typeof(string), "c", "Name", false); var elementSelector = Expression.Constant("elementSelector"); var resultOperator = new GroupResultOperator("itemName", keySelector, elementSelector); _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(keySelector, _context)) .Return(keySelector); _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(elementSelector, _context)) .Return(elementSelector); _stageMock.Replay(); _handler.HandleResultOperator(resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations(); Assert.That(_sqlStatementBuilder.GroupByExpression, Is.SameAs(keySelector)); var expectedSelectProjection = new SqlGroupingSelectExpression( new NamedExpression("key", keySelector), new NamedExpression("element", elementSelector)); SqlExpressionTreeComparer.CheckAreEqualTrees(expectedSelectProjection, _sqlStatementBuilder.SelectProjection); Assert.That( _sqlStatementBuilder.DataInfo.DataType, Is.EqualTo(typeof(IQueryable <>).MakeGenericType(typeof(IGrouping <,>).MakeGenericType(typeof(string), typeof(string))))); }
private static Expression HandleGroup( EntityQueryModelVisitor entityQueryModelVisitor, GroupResultOperator groupResultOperator, QueryModel queryModel) { var keySelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.KeySelector, queryModel.MainFromClause); var elementSelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.ElementSelector, queryModel.MainFromClause); return(Expression.Call( entityQueryModelVisitor.LinqOperatorProvider.GroupBy .MakeGenericMethod( typeof(QuerySourceScope), groupResultOperator.KeySelector.Type, groupResultOperator.ElementSelector.Type), entityQueryModelVisitor.CreateScope( entityQueryModelVisitor.Expression, entityQueryModelVisitor.StreamedSequenceInfo.ResultItemType, queryModel.MainFromClause), Expression.Lambda(keySelector, EntityQueryModelVisitor.QuerySourceScopeParameter), Expression.Lambda(elementSelector, EntityQueryModelVisitor.QuerySourceScopeParameter))); }
public static bool IsGroupingKeyOf(this MemberExpression expression, GroupResultOperator groupBy) { if (!expression.IsGroupingKey()) { return(false); } var querySource = expression.Expression as QuerySourceReferenceExpression; if (querySource == null) { return(false); } var fromClause = querySource.ReferencedQuerySource as MainFromClause; if (fromClause == null) { return(false); } var query = fromClause.FromExpression as SubQueryExpression; if (query == null) { return(false); } return(query.QueryModel.ResultOperators.Contains(groupBy)); }
public void SetUp() { _fromClause1 = ExpressionHelper.CreateMainFromClause_Int("i", typeof(int), ExpressionHelper.CreateIntQueryable()); _fromClause2 = ExpressionHelper.CreateMainFromClause_Int("j", typeof(int), ExpressionHelper.CreateIntQueryable()); _keySelector = ExpressionHelper.Resolve <int, int> (_fromClause2, j => j % 3); _elementSelector = ExpressionHelper.Resolve <int, string> (_fromClause1, i => i.ToString()); _resultOperator = new GroupResultOperator("groupings", _keySelector, _elementSelector); _cloneContext = new CloneContext(new QuerySourceMapping()); }
public void SetUp () { _fromClause1 = ExpressionHelper.CreateMainFromClause_Int ("i", typeof (int), ExpressionHelper.CreateIntQueryable ()); _fromClause2 = ExpressionHelper.CreateMainFromClause_Int ("j", typeof (int), ExpressionHelper.CreateIntQueryable ()); _keySelector = ExpressionHelper.Resolve<int, int> (_fromClause2, j => j % 3); _elementSelector = ExpressionHelper.Resolve<int, string> (_fromClause1, i => i.ToString ()); _resultOperator = new GroupResultOperator ("groupings", _keySelector, _elementSelector); _cloneContext = new CloneContext (new QuerySourceMapping ()); }
public static IEnumerable <Expression> ExtractKeyExpressions(this GroupResultOperator groupResult) { if (groupResult.KeySelector is NewExpression) { return((groupResult.KeySelector as NewExpression).Arguments); } if (groupResult.KeySelector is NewArrayExpression) { return((groupResult.KeySelector as NewArrayExpression).Expressions); } return(new [] { groupResult.KeySelector }); }
private static Expression HandleGroup( EntityQueryModelVisitor entityQueryModelVisitor, GroupResultOperator groupResultOperator, QueryModel queryModel) { var keySelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.KeySelector, queryModel.MainFromClause); var elementSelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.ElementSelector, queryModel.MainFromClause); var taskLiftingExpressionVisitor = new TaskLiftingExpressionVisitor(); var asyncElementSelector = taskLiftingExpressionVisitor.LiftTasks(elementSelector); var expression = asyncElementSelector == elementSelector ? Expression.Call( entityQueryModelVisitor.LinqOperatorProvider.GroupBy .MakeGenericMethod( entityQueryModelVisitor.Expression.Type.GetSequenceType(), keySelector.Type, elementSelector.Type), entityQueryModelVisitor.Expression, Expression.Lambda(keySelector, entityQueryModelVisitor.CurrentParameter), Expression.Lambda(elementSelector, entityQueryModelVisitor.CurrentParameter)) : Expression.Call( _groupByAsync .MakeGenericMethod( entityQueryModelVisitor.Expression.Type.GetSequenceType(), keySelector.Type, elementSelector.Type), entityQueryModelVisitor.Expression, Expression.Lambda(keySelector, entityQueryModelVisitor.CurrentParameter), Expression.Lambda( asyncElementSelector, entityQueryModelVisitor.CurrentParameter, taskLiftingExpressionVisitor.CancellationTokenParameter)); entityQueryModelVisitor.CurrentParameter = Expression.Parameter(expression.Type.GetSequenceType(), groupResultOperator.ItemName); entityQueryModelVisitor.QueryCompilationContext.AddOrUpdateMapping(groupResultOperator, entityQueryModelVisitor.CurrentParameter); return(expression); }
public void HandleResultOperator_GroupByAfterSetOperations() { _sqlStatementBuilder.SetOperationCombinedStatements.Add(SqlStatementModelObjectMother.CreateSetOperationCombinedStatement()); var keySelector = new SqlColumnDefinitionExpression(typeof(string), "c", "Name", false); var elementSelector = Expression.Constant("elementSelector"); var resultOperator = new GroupResultOperator("itemName", keySelector, elementSelector); var stage = CreateDefaultSqlPreparationStage(); _handler.HandleResultOperator(resultOperator, _sqlStatementBuilder, UniqueIdentifierGenerator, stage, _context); AssertStatementWasMovedToSubStatement(_sqlStatementBuilder); }
public static void ExtractKeyExpressions(this GroupResultOperator groupResult, IList <Expression> groupByKeys) { if (groupResult.KeySelector is NewExpression) { (groupResult.KeySelector as NewExpression).Arguments.ForEach(groupByKeys.Add); } else if (groupResult.KeySelector is NewArrayExpression) { (groupResult.KeySelector as NewArrayExpression).Expressions.ForEach(groupByKeys.Add); } else { groupByKeys.Add(groupResult.KeySelector); } }
protected virtual void VisitGroupResultOperator(GroupResultOperator groupResultOperator, QueryModel queryModel) { _groupingExpressionTransformerRegistry = new ExpressionTransformerRegistry(); // Add GROUP BY clause for the grouping key // And add transformations for any references to the key if (groupResultOperator.KeySelector.NodeType == ExpressionType.New) { // Grouping by a multipart key, so add each key to the GROUP BY clause var newExpression = (NewExpression)groupResultOperator.KeySelector; foreach (var argument in newExpression.Arguments) { _queryPartsAggregator.AddGroupByPart(GetN1QlExpression(argument)); } // Use MultiKeyExpressionTransformer to remap access to the Key property _groupingExpressionTransformerRegistry.Register( new MultiKeyExpressionTransfomer(_queryGenerationContext.GroupingQuerySource, newExpression)); } else { // Grouping by a single column _queryPartsAggregator.AddGroupByPart(GetN1QlExpression(groupResultOperator.KeySelector)); // Use KeyExpressionTransformer to remap access to the Key property _groupingExpressionTransformerRegistry.Register( new KeyExpressionTransfomer(_queryGenerationContext.GroupingQuerySource, groupResultOperator.KeySelector)); } // Add transformations for any references to the element selector if (groupResultOperator.ElementSelector.NodeType == QuerySourceReferenceExpression.ExpressionType) { _queryGenerationContext.ExtentNameProvider.LinkExtents( ((QuerySourceReferenceExpression)groupResultOperator.ElementSelector).ReferencedQuerySource, _queryGenerationContext.GroupingQuerySource.ReferencedQuerySource); } else { throw new NotSupportedException("Unsupported GroupResultOperator ElementSelector Type"); } }
public void HandleResultOperator_GroupByAfterTopExpression() { var topExpression = Expression.Constant("top"); _sqlStatementBuilder.TopExpression = topExpression; var stage = CreateDefaultSqlPreparationStage(); var keySelector = new SqlColumnDefinitionExpression(typeof(string), "c", "Name", false); var elementSelector = Expression.Constant("elementSelector"); var resultOperator = new GroupResultOperator("itemName", keySelector, elementSelector); _handler.HandleResultOperator(resultOperator, _sqlStatementBuilder, UniqueIdentifierGenerator, stage, _context); AssertStatementWasMovedToSubStatement(_sqlStatementBuilder); }
private static void RemoveCostantGroupByKeys(QueryModel queryModel, GroupResultOperator groupBy) { var keys = groupBy.ExtractKeyExpressions().Where(x => !(x is ConstantExpression)).ToList(); if (!keys.Any()) { // Remove the Group By clause completely if all the keys are constant (redundant) queryModel.ResultOperators.Remove(groupBy); } else { // Re-write the KeySelector as an object array of the non-constant keys // This should be safe because we've already re-written the select clause using the original keys groupBy.KeySelector = Expression.NewArrayInit(typeof(object), keys.Select(x => x.Type.IsValueType ? Expression.Convert(x, typeof(object)) : x)); } }
public void HandleResultOperator_GroupByAfterGroupBy() { var groupByExpression = Expression.Constant("group"); _sqlStatementBuilder.GroupByExpression = groupByExpression; var keySelector = new SqlColumnDefinitionExpression(typeof(string), "c", "Name", false); var elementSelector = Expression.Constant("elementSelector"); var resultOperator = new GroupResultOperator("itemName", keySelector, elementSelector); var fakeFromExpressionInfo = new FromExpressionInfo( new SqlTable(new ResolvedSubStatementTableInfo("sc", _sqlStatementBuilder.GetSqlStatement()), JoinSemantics.Inner), new Ordering[0], elementSelector, null); var originalStatement = _sqlStatementBuilder.GetSqlStatement(); var originalDataInfo = _sqlStatementBuilder.DataInfo; _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(keySelector, _context)) .Return(keySelector); _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(elementSelector, _context)) .Return(elementSelector); _stageMock .Expect( mock => mock.PrepareFromExpression(Arg <Expression> .Is.Anything, Arg.Is(_context), Arg <Func <ITableInfo, SqlTable> > .Is.Anything)) .Return(fakeFromExpressionInfo) .WhenCalled( mi => { var fromExpression = (Expression)mi.Arguments[0]; CheckExpressionMovedIntoSubStatement(fromExpression, originalStatement); }); _stageMock.Replay(); _handler.HandleResultOperator(resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations(); Assert.That(_sqlStatementBuilder.GroupByExpression, Is.SameAs(keySelector)); Assert.That(_sqlStatementBuilder.SqlTables.Count, Is.EqualTo(1)); Assert.That(_sqlStatementBuilder.SqlTables[0], Is.SameAs(fakeFromExpressionInfo.SqlTable)); Assert.That(_sqlStatementBuilder.DataInfo, Is.Not.SameAs(originalDataInfo)); Assert.That( _sqlStatementBuilder.DataInfo.DataType, Is.EqualTo(typeof(IQueryable <>).MakeGenericType(typeof(IGrouping <,>).MakeGenericType(typeof(string), typeof(string))))); }
public static bool IsGroupingKeyOf(this MemberExpression expression,GroupResultOperator groupBy) { if (!expression.IsGroupingKey()) { return false; } var querySource = expression.Expression as QuerySourceReferenceExpression; if (querySource == null) return false; var fromClause = querySource.ReferencedQuerySource as MainFromClause; if (fromClause == null) return false; var query = fromClause.FromExpression as SubQueryExpression; if (query == null) return false; return query.QueryModel.ResultOperators.Contains(groupBy); }
protected override ResultOperatorBase CreateResultOperator(ClauseGenerationContext clauseGenerationContext) { var resolvedKeySelector = GetResolvedKeySelector(clauseGenerationContext); var resolvedElementSelector = GetResolvedOptionalElementSelector(clauseGenerationContext); if (resolvedElementSelector == null) { // supply a default element selector if none is given // just resolve KeySelector.Parameters[0], that's the input data flowing in from the source node resolvedElementSelector = Source.Resolve(KeySelector.Parameters[0], KeySelector.Parameters[0], clauseGenerationContext); } var resultOperator = new GroupResultOperator(AssociatedIdentifier, resolvedKeySelector, resolvedElementSelector); clauseGenerationContext.AddContextInfo(this, resultOperator); return(resultOperator); }
public void HandleResultOperator_DetectConstantKeysAndReplaceWithSubStatement() { var keySelector = Expression.Constant("keySelector"); var elementSelector = Expression.Constant("elementSelector"); var resultOperator = new GroupResultOperator("itemName", keySelector, elementSelector); var preparedConstantKeySelector = Expression.Constant("test"); _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(keySelector, _context)) .Return(preparedConstantKeySelector); _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(elementSelector, _context)) .Return(elementSelector); _stageMock.Replay(); _handler.HandleResultOperator(resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations(); Assert.That(_sqlStatementBuilder.SqlTables.Count, Is.EqualTo(2)); Assert.That(_sqlStatementBuilder.SqlTables[1], Is.TypeOf(typeof(SqlTable))); Assert.That(((SqlTable)_sqlStatementBuilder.SqlTables[1]).TableInfo, Is.TypeOf(typeof(ResolvedSubStatementTableInfo))); var groupKeyTableTableInfo = (ResolvedSubStatementTableInfo)((SqlTable)_sqlStatementBuilder.SqlTables[1]).TableInfo; var expectedSelectExpression = new NamedExpression(null, preparedConstantKeySelector); SqlExpressionTreeComparer.CheckAreEqualTrees(expectedSelectExpression, groupKeyTableTableInfo.SqlStatement.SelectProjection); var expectedStatement = new SqlStatementBuilder { DataInfo = new StreamedSequenceInfo(typeof(IEnumerable <string>), groupKeyTableTableInfo.SqlStatement.SelectProjection), SelectProjection = groupKeyTableTableInfo.SqlStatement.SelectProjection } .GetSqlStatement(); Assert.That(groupKeyTableTableInfo.SqlStatement, Is.EqualTo(expectedStatement)); var expectedGroupGyExpression = new SqlTableReferenceExpression(_sqlStatementBuilder.SqlTables[1]); SqlExpressionTreeComparer.CheckAreEqualTrees(_sqlStatementBuilder.GroupByExpression, expectedGroupGyExpression); SqlExpressionTreeComparer.CheckAreEqualTrees( _sqlStatementBuilder.SelectProjection, SqlGroupingSelectExpression.CreateWithNames(expectedGroupGyExpression, elementSelector)); }
public static bool IsGroupingElementOf(this QuerySourceReferenceExpression expression, GroupResultOperator groupBy) { var fromClause = expression.ReferencedQuerySource as MainFromClause; if (fromClause == null) return false; var innerQuerySource = fromClause.FromExpression as QuerySourceReferenceExpression; if (innerQuerySource == null) return false; if (innerQuerySource.ReferencedQuerySource.ItemName != groupBy.ItemName || innerQuerySource.ReferencedQuerySource.ItemType != groupBy.ItemType) return false; var innerFromClause = innerQuerySource.ReferencedQuerySource as MainFromClause; if (innerFromClause == null) return false; var query = innerFromClause.FromExpression as SubQueryExpression; if (query == null) return false; return query.QueryModel.ResultOperators.Contains(groupBy); }
public void HandleResultOperator_TransformSubqueriesUsedAsGroupByKeys() { var keySelector = Expression.Constant("keySelector"); var elementSelector = Expression.Constant("elementSelector"); var resultOperator = new GroupResultOperator("itemName", keySelector, elementSelector); var sqlStatement = SqlStatementModelObjectMother.CreateSqlStatement_Single(); var preparedSubStatementKeySelector = new SqlSubStatementExpression(sqlStatement); _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(keySelector, _context)) .Return(preparedSubStatementKeySelector); _stageMock .Expect(mock => mock.PrepareResultOperatorItemExpression(elementSelector, _context)) .Return(elementSelector); _stageMock.Replay(); _handler.HandleResultOperator(resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations(); Assert.That(_sqlStatementBuilder.SqlTables.Count, Is.EqualTo(2)); Assert.That(_sqlStatementBuilder.SqlTables[1], Is.TypeOf(typeof(SqlTable))); Assert.That(((SqlTable)_sqlStatementBuilder.SqlTables[1]).TableInfo, Is.TypeOf(typeof(ResolvedSubStatementTableInfo))); var groupKeyTableTableInfo = (ResolvedSubStatementTableInfo)((SqlTable)_sqlStatementBuilder.SqlTables[1]).TableInfo; var expectedStatement = new SqlStatementBuilder(sqlStatement) { DataInfo = new StreamedSequenceInfo(typeof(IEnumerable <int>), sqlStatement.SelectProjection) } .GetSqlStatement(); Assert.That(groupKeyTableTableInfo.SqlStatement, Is.EqualTo(expectedStatement)); var expectedGroupGyExpression = new SqlTableReferenceExpression(_sqlStatementBuilder.SqlTables[1]); SqlExpressionTreeComparer.CheckAreEqualTrees(_sqlStatementBuilder.GroupByExpression, expectedGroupGyExpression); SqlExpressionTreeComparer.CheckAreEqualTrees( _sqlStatementBuilder.SelectProjection, SqlGroupingSelectExpression.CreateWithNames(expectedGroupGyExpression, elementSelector)); }
private static Expression HandleGroup( EntityQueryModelVisitor entityQueryModelVisitor, GroupResultOperator groupResultOperator, QueryModel queryModel) { var sequenceType = entityQueryModelVisitor.Expression.Type.GetSequenceType(); var keySelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.KeySelector, queryModel.MainFromClause); var elementSelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.ElementSelector, queryModel.MainFromClause); var expression = Expression.Call( entityQueryModelVisitor.LinqOperatorProvider.GroupBy .MakeGenericMethod( sequenceType, keySelector.Type, elementSelector.Type), entityQueryModelVisitor.Expression, Expression.Lambda(keySelector, entityQueryModelVisitor.CurrentParameter), Expression.Lambda(elementSelector, entityQueryModelVisitor.CurrentParameter)); entityQueryModelVisitor.CurrentParameter = Expression.Parameter(sequenceType, groupResultOperator.ItemName); entityQueryModelVisitor .AddOrUpdateMapping(groupResultOperator, entityQueryModelVisitor.CurrentParameter); return(expression); }
private static void FlattenSubQuery(QueryModel queryModel, QueryModel subQueryModel, GroupResultOperator groupBy) { foreach (var resultOperator in queryModel.ResultOperators.Where(resultOperator => !AcceptableOuterResultOperators.Contains(resultOperator.GetType()))) { throw new NotImplementedException("Cannot use group by with the " + resultOperator.GetType().Name + " result operator."); } // Move the result operator up. SubQueryFromClauseFlattener.InsertResultOperators(subQueryModel.ResultOperators, queryModel); for (var i = 0; i < queryModel.BodyClauses.Count; i++) { var clause = queryModel.BodyClauses[i]; clause.TransformExpressions(s => GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryModel)); //all outer where clauses actually are having clauses var whereClause = clause as WhereClause; if (whereClause != null) { queryModel.BodyClauses.RemoveAt(i); queryModel.BodyClauses.Insert(i, new NhHavingClause(whereClause.Predicate)); } } foreach (var bodyClause in subQueryModel.BodyClauses) queryModel.BodyClauses.Add(bodyClause); // Replace the outer select clause... queryModel.SelectClause.TransformExpressions(s => GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryModel)); // Point all query source references to the outer from clause var visitor = new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryModel.MainFromClause); queryModel.TransformExpressions(visitor.Swap); // Replace the outer query source queryModel.MainFromClause = subQueryModel.MainFromClause; }
public void TransformExpressions() { var oldExpression1 = ExpressionHelper.CreateExpression(); var oldExpression2 = ExpressionHelper.CreateExpression(); var newExpression1 = ExpressionHelper.CreateExpression(); var newExpression2 = ExpressionHelper.CreateExpression(); var resultOperator = new GroupResultOperator("x", oldExpression1, oldExpression2); resultOperator.TransformExpressions(ex => { if (ex == oldExpression1) { return(newExpression1); } else { Assert.That(ex, Is.SameAs(oldExpression2)); return(newExpression2); } }); Assert.That(resultOperator.KeySelector, Is.SameAs(newExpression1)); Assert.That(resultOperator.ElementSelector, Is.SameAs(newExpression2)); }
public void HandleResultOperator_TransformSubqueriesUsedAsGroupByKeys () { var keySelector = Expression.Constant ("keySelector"); var elementSelector = Expression.Constant ("elementSelector"); var resultOperator = new GroupResultOperator ("itemName", keySelector, elementSelector); var sqlStatement = SqlStatementModelObjectMother.CreateSqlStatement_Single(); var preparedSubStatementKeySelector = new SqlSubStatementExpression (sqlStatement); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (keySelector, _context)) .Return (preparedSubStatementKeySelector); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (elementSelector, _context)) .Return (elementSelector); _stageMock.Replay (); _handler.HandleResultOperator (resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations (); Assert.That (_sqlStatementBuilder.SqlTables.Count, Is.EqualTo (2)); Assert.That (_sqlStatementBuilder.SqlTables[1], Is.TypeOf (typeof(SqlTable))); Assert.That (((SqlTable) _sqlStatementBuilder.SqlTables[1]).TableInfo, Is.TypeOf (typeof (ResolvedSubStatementTableInfo))); var groupKeyTableTableInfo = (ResolvedSubStatementTableInfo) ((SqlTable) _sqlStatementBuilder.SqlTables[1]).TableInfo; var expectedStatement = new SqlStatementBuilder (sqlStatement) { DataInfo = new StreamedSequenceInfo (typeof (IEnumerable<int>), sqlStatement.SelectProjection) } .GetSqlStatement(); Assert.That (groupKeyTableTableInfo.SqlStatement, Is.EqualTo (expectedStatement)); var expectedGroupGyExpression = new SqlTableReferenceExpression (_sqlStatementBuilder.SqlTables[1]); SqlExpressionTreeComparer.CheckAreEqualTrees (_sqlStatementBuilder.GroupByExpression, expectedGroupGyExpression); SqlExpressionTreeComparer.CheckAreEqualTrees ( _sqlStatementBuilder.SelectProjection, SqlGroupingSelectExpression.CreateWithNames (expectedGroupGyExpression, elementSelector)); }
private static void RemoveCostantGroupByKeys(QueryModel queryModel, GroupResultOperator groupBy) { var keys = groupBy.ExtractKeyExpressions().Where(x => !(x is ConstantExpression)).ToList(); if (!keys.Any()) { // Remove the Group By clause completely if all the keys are constant (redundant) queryModel.ResultOperators.Remove(groupBy); } else { // Re-write the KeySelector as an object array of the non-constant keys // This should be safe because we've already re-written the select clause using the original keys groupBy.KeySelector = Expression.NewArrayInit(typeof (object), keys.Select(x => x.Type.IsValueType ? Expression.Convert(x, typeof(object)) : x)); } }
public static Expression Visit(GroupResultOperator groupBy) { return VisitInternal(groupBy.KeySelector); }
public static Expression ReWrite(Expression expression, GroupResultOperator groupBy, QueryModel model) { var visitor = new GroupBySelectClauseRewriter(groupBy, model); return TransparentIdentifierRemovingExpressionTreeVisitor.ReplaceTransparentIdentifiers(visitor.VisitExpression(expression)); }
private GroupBySelectClauseRewriter(GroupResultOperator groupBy, QueryModel model) { _groupBy = groupBy; _model = model; }
public void HandleResultOperator_GroupByAfterTopExpression () { var topExpression = Expression.Constant ("top"); _sqlStatementBuilder.TopExpression = topExpression; var keySelector = new SqlColumnDefinitionExpression(typeof(string), "c", "Name", false); var elementSelector = Expression.Constant ("elementSelector"); var resultOperator = new GroupResultOperator ("itemName", keySelector, elementSelector); var originalStatement = _sqlStatementBuilder.GetSqlStatement (); var originalDataInfo = _sqlStatementBuilder.DataInfo; var fakeFromExpressionInfo = new FromExpressionInfo ( new SqlTable (new ResolvedSubStatementTableInfo("sc", originalStatement), JoinSemantics.Inner), new Ordering[0], elementSelector, null); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (keySelector, _context)) .Return (keySelector); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (elementSelector, _context)) .Return (elementSelector); _stageMock .Expect ( mock => mock.PrepareFromExpression (Arg<Expression>.Is.Anything, Arg.Is (_context), Arg<Func<ITableInfo, SqlTable>>.Is.Anything)) .Return (fakeFromExpressionInfo) .WhenCalled (mi => { var fromExpression = (Expression) mi.Arguments[0]; CheckExpressionMovedIntoSubStatement (fromExpression, originalStatement); }); _handler.HandleResultOperator (resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations(); Assert.That (_sqlStatementBuilder.GroupByExpression, Is.SameAs (keySelector)); Assert.That (_sqlStatementBuilder.SqlTables.Count, Is.EqualTo (1)); Assert.That (_sqlStatementBuilder.SqlTables[0], Is.SameAs (fakeFromExpressionInfo.SqlTable)); Assert.That (_sqlStatementBuilder.DataInfo, Is.Not.SameAs (originalDataInfo)); Assert.That ( _sqlStatementBuilder.DataInfo.DataType, Is.EqualTo (typeof (IQueryable<>).MakeGenericType (typeof (IGrouping<,>).MakeGenericType (typeof (string), typeof (string))))); }
private GroupBySelectClauseRewriter(GroupResultOperator groupBy, QueryModel model) { _groupBy = groupBy; _model = model; _nominatedKeySelector = GroupKeyNominator.Visit(groupBy); }
protected virtual void VisitGroupResultOperator(GroupResultOperator groupResultOperator, QueryModel queryModel) { _groupingExpressionTransformerRegistry = new ExpressionTransformerRegistry(); // Add GROUP BY clause for the grouping key // And add transformations for any references to the key if (groupResultOperator.KeySelector.NodeType == ExpressionType.New) { // Grouping by a multipart key, so add each key to the GROUP BY clause var newExpression = (NewExpression) groupResultOperator.KeySelector; foreach (var argument in newExpression.Arguments) { _queryPartsAggregator.AddGroupByPart(GetN1QlExpression(argument)); } // Use MultiKeyExpressionTransformer to remap access to the Key property _groupingExpressionTransformerRegistry.Register( new MultiKeyExpressionTransfomer(_queryGenerationContext.GroupingQuerySource, newExpression)); } else { // Grouping by a single column _queryPartsAggregator.AddGroupByPart(GetN1QlExpression(groupResultOperator.KeySelector)); // Use KeyExpressionTransformer to remap access to the Key property _groupingExpressionTransformerRegistry.Register( new KeyExpressionTransfomer(_queryGenerationContext.GroupingQuerySource, groupResultOperator.KeySelector)); } // Add transformations for any references to the element selector if (groupResultOperator.ElementSelector.NodeType == QuerySourceReferenceExpression.ExpressionType) { _queryGenerationContext.ExtentNameProvider.LinkExtents( ((QuerySourceReferenceExpression) groupResultOperator.ElementSelector).ReferencedQuerySource, _queryGenerationContext.GroupingQuerySource.ReferencedQuerySource); } else { throw new NotSupportedException("Unsupported GroupResultOperator ElementSelector Type"); } }
public NonAggregatingGroupBy(GroupResultOperator groupBy) { GroupBy = groupBy; }
public static IEnumerable <Expression> ExtractKeyExpressions(this GroupResultOperator groupResult) { return(groupResult.KeySelector.ExtractKeyExpressions()); }
public static Expression ReWrite(Expression expression, GroupResultOperator groupBy, QueryModel model) { var visitor = new GroupBySelectClauseRewriter(groupBy, model); return(TransparentIdentifierRemovingExpressionTreeVisitor.ReplaceTransparentIdentifiers(visitor.VisitExpression(expression))); }
public void TransformExpressions () { var oldExpression1 = ExpressionHelper.CreateExpression (); var oldExpression2 = ExpressionHelper.CreateExpression (); var newExpression1 = ExpressionHelper.CreateExpression (); var newExpression2 = ExpressionHelper.CreateExpression (); var resultOperator = new GroupResultOperator ("x", oldExpression1, oldExpression2); resultOperator.TransformExpressions (ex => { if (ex == oldExpression1) return newExpression1; else { Assert.That (ex, Is.SameAs (oldExpression2)); return newExpression2; } }); Assert.That (resultOperator.KeySelector, Is.SameAs (newExpression1)); Assert.That (resultOperator.ElementSelector, Is.SameAs (newExpression2)); }
public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index) { resultOptionType = resultOptionType ?? queryModel.SelectClause.Selector.Type; if (resultOperator is CastResultOperator) { CastResultOperator castResultOperator = (CastResultOperator)resultOperator; Type castType = castResultOperator.CastItemType; MethodInfo cast = GetMethod("Cast", expression.Type).MakeGenericMethod(castType); resultOptionType = castType; expression = Expression.Call(cast, expression); return; } if (resultOperator is AllResultOperator) { AllResultOperator allResultOperator = (AllResultOperator)resultOperator; ParameterExpression parameterExpression = Expression.Parameter(selectorType, "p"); Expression predicateUpdate = UpdateExpressionVisitor.Update(allResultOperator.Predicate, new[] { parameterExpression }, dbContext, queryContext); Expression allLamda = Expression.Lambda(predicateUpdate, parameterExpression); MethodInfo all = GetMethod("All", expression.Type, 1).MakeGenericMethod(selectorType); expression = Expression.Call(all, new[] { expression, allLamda }); return; } if (resultOperator is FirstResultOperator) { FirstResultOperator firstResultOperator = (FirstResultOperator)resultOperator; if (firstResultOperator.ReturnDefaultWhenEmpty) { MethodInfo firstOrDefault = GetMethod("FirstOrDefault", expression.Type, 0).MakeGenericMethod(selectorType); expression = Expression.Call(firstOrDefault, new[] { expression }); } else { MethodInfo first = GetMethod("First", expression.Type, 0).MakeGenericMethod(selectorType); expression = Expression.Call(first, new[] { expression }); } return; } if (resultOperator is SingleResultOperator) { SingleResultOperator singleResultOperator = (SingleResultOperator)resultOperator; if (singleResultOperator.ReturnDefaultWhenEmpty) { MethodInfo firstOrDefault = GetMethod("SingleOrDefault", expression.Type, 0).MakeGenericMethod(selectorType); expression = Expression.Call(firstOrDefault, new[] { expression }); } else { MethodInfo first = GetMethod("Single", expression.Type, 0).MakeGenericMethod(selectorType); expression = Expression.Call(first, new[] { expression }); } return; } if (resultOperator is AnyResultOperator) { MethodInfo any = GetMethod("Any", expression.Type).MakeGenericMethod(selectorType); expression = Expression.Call(any, new[] { expression }); return; } if (resultOperator is TrackingResultOperator) { MethodInfo asNoTracking = typeof(EntityFrameworkQueryableExtensions).GetMethod("AsNoTracking").MakeGenericMethod(selectorType); expression = Expression.Call(asNoTracking, new[] { expression }); return; } if (resultOperator is CountResultOperator) { MethodInfo count = GetMethod("Count", expression.Type).MakeGenericMethod(selectorType); expression = Expression.Call(count, new[] { expression }); return; } if (resultOperator is AverageResultOperator) { MethodInfo average = GetAgregateMethod("Average", expression.Type, selectorType); expression = Expression.Call(average, new[] { expression }); return; } if (resultOperator is ContainsResultOperator) { ContainsResultOperator containsResultOperator = (ContainsResultOperator)resultOperator; Expression valExp; object value; ParameterExpression paramExp = containsResultOperator.Item as ParameterExpression; if (paramExp != null && queryContext.ParameterValues.TryGetValue(paramExp.Name, out value)) { valExp = Expression.Constant(value); } else { valExp = containsResultOperator.Item; } if (containsResultOperator.Item is SubQueryExpression) { SubQueryExpression subQueryExpression = (SubQueryExpression)containsResultOperator.Item; QueryModelVisitor queryModelVisitor = new QueryModelVisitor(dbContext, queryContext); queryModelVisitor.VisitQueryModel(subQueryExpression.QueryModel); valExp = queryModelVisitor.expression; } MethodInfo contains = GetMethod("Contains", expression.Type, 1).MakeGenericMethod(selectorType); expression = Expression.Call(contains, new[] { expression, valExp }); return; } if (resultOperator is DefaultIfEmptyResultOperator) { DefaultIfEmptyResultOperator defaultIfEmptyResultOperator = (DefaultIfEmptyResultOperator)resultOperator; MethodInfo defaultIfEmpty; if (defaultIfEmptyResultOperator.OptionalDefaultValue != null) { defaultIfEmpty = GetMethod("DefaultIfEmpty", expression.Type, 1).MakeGenericMethod(selectorType); expression = Expression.Call(defaultIfEmpty, new[] { expression, defaultIfEmptyResultOperator.OptionalDefaultValue }); } defaultIfEmpty = GetMethod("DefaultIfEmpty", expression.Type).MakeGenericMethod(selectorType); expression = Expression.Call(defaultIfEmpty, expression); return; } if (resultOperator is DistinctResultOperator) { MethodInfo distinct = GetMethod("Distinct", expression.Type).MakeGenericMethod(selectorType); expression = Expression.Call(distinct, expression); return; } if (resultOperator is GroupResultOperator) { GroupResultOperator groupResultOperator = (GroupResultOperator)resultOperator; Type keySelectorType = GetTypeParameter(groupResultOperator.KeySelector); ParameterExpression keyExpressionParam = Expression.Parameter(keySelectorType, "p"); Expression keyExpression = UpdateExpressionVisitor.Update(groupResultOperator.KeySelector, new[] { keyExpressionParam }, dbContext, queryContext); LambdaExpression keyLambdaExpression = Expression.Lambda(keyExpression, keyExpressionParam); Type elementSelectorType = GetTypeParameter(groupResultOperator.ElementSelector); ParameterExpression ElementExpressionParam = Expression.Parameter(elementSelectorType, "p"); Expression ElementExpression = UpdateExpressionVisitor.Update(groupResultOperator.ElementSelector, new[] { ElementExpressionParam }, dbContext, queryContext); LambdaExpression ElementLambdaExpression = Expression.Lambda(ElementExpression, ElementExpressionParam); Type tSource = queryModel.MainFromClause.ItemType; Type tKey = keyExpression.Type; Type tElement = ElementExpression.Type; Type tResult = queryModel.ResultTypeOverride; MethodInfo groupBy = GetMethods("GroupBy", expression.Type, 2).Where(p => p.GetParameters()[2].Name == "elementSelector").Single(). MakeGenericMethod(tSource, tKey, tElement); expression = Expression.Call(groupBy, new[] { expression, keyLambdaExpression, ElementLambdaExpression }); return; } if (resultOperator is LastResultOperator) { LastResultOperator lastResultOperator = (LastResultOperator)resultOperator; if (lastResultOperator.ReturnDefaultWhenEmpty) { MethodInfo lastOrDefault = GetMethod("LastOrDefault", expression.Type, 0).MakeGenericMethod(selectorType); expression = Expression.Call(lastOrDefault, new[] { expression }); } else { MethodInfo last = GetMethod("Last", expression.Type, 0).MakeGenericMethod(selectorType); expression = Expression.Call(last, new[] { expression }); } return; } if (resultOperator is LongCountResultOperator) { MethodInfo longCount = GetMethod("LongCount", expression.Type).MakeGenericMethod(selectorType); expression = Expression.Call(longCount, new[] { expression }); return; } if (resultOperator is MaxResultOperator) { MethodInfo max = GetMethod("Max", expression.Type).MakeGenericMethod(selectorType); expression = Expression.Call(max, expression); return; } if (resultOperator is MinResultOperator) { MethodInfo min = GetMethod("Min", expression.Type).MakeGenericMethod(selectorType); expression = Expression.Call(min, expression); return; } if (resultOperator is SumResultOperator) { MethodInfo sum = GetAgregateMethod("Sum", expression.Type, selectorType); expression = Expression.Call(sum, expression); return; } if (resultOperator is SkipResultOperator) { SkipResultOperator skipResultOperator = (SkipResultOperator)resultOperator; Expression expVal; object value; ParameterExpression paramExp = skipResultOperator.Count as ParameterExpression; if (paramExp != null && queryContext.ParameterValues.TryGetValue(paramExp.Name, out value)) { expVal = Expression.Constant(value); } else { expVal = skipResultOperator.Count; } MethodInfo skip = GetMethod("Skip", expression.Type, 1).MakeGenericMethod(selectorType); expression = Expression.Call(skip, new[] { expression, expVal }); return; } if (resultOperator is TakeResultOperator) { TakeResultOperator takeResultOperator = (TakeResultOperator)resultOperator; Expression expVal; object value; ParameterExpression paramExp = takeResultOperator.Count as ParameterExpression; if (paramExp != null && queryContext.ParameterValues.TryGetValue(paramExp.Name, out value)) { expVal = Expression.Constant(value); } else { expVal = takeResultOperator.Count; } MethodInfo take = GetMethod("Take", expression.Type, 1).MakeGenericMethod(selectorType); expression = Expression.Call(take, new[] { expression, expVal }); return; } if (resultOperator is IncludeResultOperator) { IncludeResultOperator includeResultOperator = (IncludeResultOperator)resultOperator; Expression includeExpression = includeResultOperator.NavigationPropertyPath; Type paramExpressionType = null; ParameterExpression parameterExpression = null; if (includeExpression is MemberExpression) { MemberExpression memberExpression = (MemberExpression)includeExpression; paramExpressionType = memberExpression.Expression.Type; parameterExpression = Expression.Parameter(paramExpressionType, "p"); includeExpression = Expression.Property(parameterExpression, memberExpression.Member.Name); } else { paramExpressionType = GetTypeParameter(includeExpression); parameterExpression = Expression.Parameter(paramExpressionType, "p"); } Expression updateOuterExpression = UpdateExpressionVisitor.Update(includeExpression, new[] { parameterExpression }, dbContext, queryContext); LambdaExpression lambdaIncludeExpression = Expression.Lambda(updateOuterExpression, parameterExpression); MethodInfo include = typeof(EntityFrameworkQueryableExtensions).GetMethods().First(m => m.Name == "Include").MakeGenericMethod(selectorType, updateOuterExpression.Type); expression = Expression.Call(include, new[] { expression, lambdaIncludeExpression }); if (includeResultOperator.ChainedNavigationProperties != null) { foreach (PropertyInfo propertyInfo in includeResultOperator.ChainedNavigationProperties) { Type propertyType = propertyInfo.PropertyType; Type argument = expression.Type.GetGenericArguments().Last(); MethodInfo thenInclude; Type realType; if (typeof(IEnumerable).IsAssignableFrom(argument)) { realType = argument.GetGenericArguments().First(); thenInclude = ThenIncludeCollection.MakeGenericMethod(includeResultOperator.QuerySource.ItemType, realType, propertyType); } else { realType = argument; thenInclude = ThenIncludeProperty.MakeGenericMethod(includeResultOperator.QuerySource.ItemType, realType, propertyType); } ParameterExpression parameterThenIncludeExpression = Expression.Parameter(realType, "p"); MemberExpression property = Expression.Property(parameterThenIncludeExpression, propertyInfo); LambdaExpression lambdaThenIncludeExpression = Expression.Lambda(property, parameterThenIncludeExpression); expression = Expression.Call(thenInclude, new[] { expression, lambdaThenIncludeExpression }); } } return; } if (resultOperator is OfTypeResultOperator) { OfTypeResultOperator ofTypeResultOperator = (OfTypeResultOperator)resultOperator; selectorType = ofTypeResultOperator.SearchedItemType; var miOfType = GetMethod("OfType", expression.Type).MakeGenericMethod(ofTypeResultOperator.SearchedItemType); expression = Expression.Call(miOfType, new[] { expression }); return; } throw new NotSupportedException(); }
private static Expression HandleGroup( EntityQueryModelVisitor entityQueryModelVisitor, GroupResultOperator groupResultOperator, QueryModel queryModel) { var keySelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.KeySelector, queryModel.MainFromClause); var elementSelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.ElementSelector, queryModel.MainFromClause); return Expression.Call( entityQueryModelVisitor.LinqOperatorProvider.GroupBy .MakeGenericMethod( typeof(QuerySourceScope), groupResultOperator.KeySelector.Type, groupResultOperator.ElementSelector.Type), entityQueryModelVisitor.CreateScope( entityQueryModelVisitor.Expression, entityQueryModelVisitor.StreamedSequenceInfo.ResultItemType, queryModel.MainFromClause), Expression.Lambda(keySelector, EntityQueryModelVisitor.QuerySourceScopeParameter), Expression.Lambda(elementSelector, EntityQueryModelVisitor.QuerySourceScopeParameter)); }
public static Expression ReWrite(Expression expression, GroupResultOperator groupBy, QueryModel model) { var visitor = new GroupBySelectClauseRewriter(groupBy, model); return visitor.VisitExpression(expression); }
private void ProcessGroupByOperator(GroupResultOperator resultOperator) { var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator); visitor.Visit(resultOperator.KeySelector); _groupByClause = _hqlTreeBuilder.GroupBy(); _groupByClause.AddChild(visitor.GetHqlTreeNodes().Single()); }
internal static bool TryGetGroupResultOperator(this MemberExpression keyExpression, out GroupResultOperator groupBy) { if (keyExpression.IsGroupingKey() && keyExpression.Expression is QuerySourceReferenceExpression querySource && querySource.ReferencedQuerySource is MainFromClause fromClause && fromClause.FromExpression is SubQueryExpression query) { groupBy = query.QueryModel.ResultOperators .OfType <GroupResultOperator>() .FirstOrDefault(o => o.KeySelector.Type == keyExpression.Type); return(groupBy != null); } groupBy = null; return(false); }
public void HandleResultOperator_DetectConstantKeysAndReplaceWithSubStatement () { var keySelector = Expression.Constant ("keySelector"); var elementSelector = Expression.Constant ("elementSelector"); var resultOperator = new GroupResultOperator ("itemName", keySelector, elementSelector); var preparedConstantKeySelector = Expression.Constant ("test"); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (keySelector, _context)) .Return (preparedConstantKeySelector); _stageMock .Expect (mock => mock.PrepareResultOperatorItemExpression (elementSelector, _context)) .Return (elementSelector); _stageMock.Replay (); _handler.HandleResultOperator (resultOperator, _sqlStatementBuilder, _generator, _stageMock, _context); _stageMock.VerifyAllExpectations (); Assert.That (_sqlStatementBuilder.SqlTables.Count, Is.EqualTo (2)); Assert.That (_sqlStatementBuilder.SqlTables[1], Is.TypeOf (typeof (SqlTable))); Assert.That (((SqlTable) _sqlStatementBuilder.SqlTables[1]).TableInfo, Is.TypeOf (typeof (ResolvedSubStatementTableInfo))); var groupKeyTableTableInfo = (ResolvedSubStatementTableInfo) ((SqlTable) _sqlStatementBuilder.SqlTables[1]).TableInfo; var expectedSelectExpression = new NamedExpression (null, preparedConstantKeySelector); SqlExpressionTreeComparer.CheckAreEqualTrees (expectedSelectExpression, groupKeyTableTableInfo.SqlStatement.SelectProjection); var expectedStatement = new SqlStatementBuilder { DataInfo = new StreamedSequenceInfo (typeof (IEnumerable<string>), groupKeyTableTableInfo.SqlStatement.SelectProjection), SelectProjection = groupKeyTableTableInfo.SqlStatement.SelectProjection } .GetSqlStatement (); Assert.That (groupKeyTableTableInfo.SqlStatement, Is.EqualTo (expectedStatement)); var expectedGroupGyExpression = new SqlTableReferenceExpression (_sqlStatementBuilder.SqlTables[1]); SqlExpressionTreeComparer.CheckAreEqualTrees (_sqlStatementBuilder.GroupByExpression, expectedGroupGyExpression); SqlExpressionTreeComparer.CheckAreEqualTrees ( _sqlStatementBuilder.SelectProjection, SqlGroupingSelectExpression.CreateWithNames (expectedGroupGyExpression, elementSelector)); }
public static bool IsGroupingElementOf(this QuerySourceReferenceExpression expression, GroupResultOperator groupBy) { var fromClause = expression.ReferencedQuerySource as MainFromClause; if (fromClause == null) { return(false); } var innerQuerySource = fromClause.FromExpression as QuerySourceReferenceExpression; if (innerQuerySource == null) { return(false); } if (innerQuerySource.ReferencedQuerySource.ItemName != groupBy.ItemName || innerQuerySource.ReferencedQuerySource.ItemType != groupBy.ItemType) { return(false); } var innerFromClause = innerQuerySource.ReferencedQuerySource as MainFromClause; if (innerFromClause == null) { return(false); } var query = innerFromClause.FromExpression as SubQueryExpression; if (query == null) { return(false); } return(query.QueryModel.ResultOperators.Contains(groupBy)); }
public static Expression ReWrite(Expression expression, GroupResultOperator groupBy, QueryModel model) { var visitor = new GroupBySelectClauseRewriter(groupBy, model); return(visitor.VisitExpression(expression)); }
private static Expression HandleGroup( EntityQueryModelVisitor entityQueryModelVisitor, GroupResultOperator groupResultOperator, QueryModel queryModel) { var keySelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.KeySelector, queryModel.MainFromClause); var elementSelector = entityQueryModelVisitor .ReplaceClauseReferences( groupResultOperator.ElementSelector, queryModel.MainFromClause); var expression = Expression.Call( entityQueryModelVisitor.LinqOperatorProvider.GroupBy .MakeGenericMethod( entityQueryModelVisitor.Expression.Type.GetSequenceType(), keySelector.Type, elementSelector.Type), entityQueryModelVisitor.Expression, Expression.Lambda(keySelector, entityQueryModelVisitor.CurrentParameter), Expression.Lambda(elementSelector, entityQueryModelVisitor.CurrentParameter)); entityQueryModelVisitor.CurrentParameter = Expression.Parameter(expression.Type.GetSequenceType(), groupResultOperator.ItemName); entityQueryModelVisitor .AddOrUpdateMapping(groupResultOperator, entityQueryModelVisitor.CurrentParameter); return expression; }
public KeySelectorVisitor(GroupResultOperator groupBy) { _groupBy = groupBy; }
protected override ResultOperatorBase CreateResultOperator (ClauseGenerationContext clauseGenerationContext) { var resolvedKeySelector = GetResolvedKeySelector (clauseGenerationContext); var resolvedElementSelector = GetResolvedOptionalElementSelector (clauseGenerationContext); if (resolvedElementSelector == null) { // supply a default element selector if none is given // just resolve KeySelector.Parameters[0], that's the input data flowing in from the source node resolvedElementSelector = Source.Resolve (_keySelector.Parameters[0], _keySelector.Parameters[0], clauseGenerationContext); } var resultOperator = new GroupResultOperator (AssociatedIdentifier, resolvedKeySelector, resolvedElementSelector); clauseGenerationContext.AddContextInfo (this, resultOperator); return resultOperator; }
public static Expression Visit(GroupResultOperator groupBy) { return(VisitInternal(groupBy.KeySelector)); }
private static void FlattenSubQuery(QueryModel queryModel, QueryModel subQueryModel, GroupResultOperator groupBy) { foreach (var resultOperator in queryModel.ResultOperators.Where(resultOperator => !AcceptableOuterResultOperators.Contains(resultOperator.GetType()))) { throw new NotImplementedException("Cannot use group by with the " + resultOperator.GetType().Name + " result operator."); } // Move the result operator up. SubQueryFromClauseFlattener.InsertResultOperators(subQueryModel.ResultOperators, queryModel); for (var i = 0; i < queryModel.BodyClauses.Count; i++) { var clause = queryModel.BodyClauses[i]; clause.TransformExpressions(s => GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryModel)); //all outer where clauses actually are having clauses var whereClause = clause as WhereClause; if (whereClause != null) { queryModel.BodyClauses[i] = new NhHavingClause(whereClause.Predicate); } } foreach (var bodyClause in subQueryModel.BodyClauses) { queryModel.BodyClauses.Add(bodyClause); } // Replace the outer select clause... queryModel.SelectClause.TransformExpressions(s => GroupBySelectClauseRewriter.ReWrite(s, groupBy, subQueryModel)); // Point all query source references to the outer from clause var visitor = new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryModel.MainFromClause); queryModel.TransformExpressions(visitor.Swap); // Replace the outer query source queryModel.MainFromClause = subQueryModel.MainFromClause; }