SqlGroupingSelectExpression represents the data returned by a Group-By query.
Inheritance: Remotion.Linq.Clauses.Expressions.ExtensionExpression
 public void SetUp ()
 {
   _context = new MappingResolutionContext();
   _entityExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook), null, "c");
   _groupingSelectExpression = new SqlGroupingSelectExpression (Expression.Constant ("key"), Expression.Constant ("element"));
   _sqlTable = new SqlTable (new ResolvedSimpleTableInfo (typeof (Cook), "CookTable", "c"), JoinSemantics.Inner);
 }
    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 AddGroupReferenceMapping (SqlGroupingSelectExpression groupingSelectExpression, SqlTableBase sqlTable)
    {
      ArgumentUtility.CheckNotNull ("groupingSelectExpression", groupingSelectExpression);
      ArgumentUtility.CheckNotNull ("sqlTable", sqlTable);

      _groupReferenceMapping[groupingSelectExpression] = sqlTable;
    }
    public virtual Expression VisitSqlGroupingSelectExpression (SqlGroupingSelectExpression expression)
    {
      ArgumentUtility.CheckNotNull ("expression", expression);

      var groupExpressions = new[] { expression.KeyExpression }.Concat (expression.AggregationExpressions);

      CommandBuilder.AppendSeparated (", ", groupExpressions, (cb, exp) => VisitExpression (exp));

      return expression;
    }
    public SqlTableBase GetReferencedGroupSource (SqlGroupingSelectExpression groupingSelectExpression)
    {
      ArgumentUtility.CheckNotNull ("groupingSelectExpression", groupingSelectExpression);
      SqlTableBase result;
      if (_groupReferenceMapping.TryGetValue (groupingSelectExpression, out result))
        return result;

      var message = string.Format (
          "No associated table found for grouping select expression '{0}'.", 
          FormattingExpressionTreeVisitor.Format (groupingSelectExpression));
      throw new InvalidOperationException (message);
    }
    public void SetUp ()
    {
      _keyExpression = Expression.Constant ("key");
      _elementExpression = Expression.Constant ("element");

      _aggregateExpression1 = Expression.Constant ("agg1");
      _aggregateExpression2 = Expression.Constant ("agg2");

      _sqlGroupingSelectExpression = new SqlGroupingSelectExpression (
          _keyExpression, 
          _elementExpression, 
          new [] { _aggregateExpression1 });
    }
Exemple #7
0
        protected override Expression VisitChildren(ExpressionTreeVisitor visitor)
        {
            ArgumentUtility.CheckNotNull("visitor", visitor);

            var newKeyExpression     = visitor.VisitExpression(KeyExpression);
            var newElementExpression = visitor.VisitExpression(ElementExpression);

            var originalAggregationExpressions = AggregationExpressions;
            var newAggregationExpressions      = visitor.VisitAndConvert(originalAggregationExpressions, "VisitChildren");

            if (newKeyExpression != KeyExpression ||
                newElementExpression != ElementExpression ||
                newAggregationExpressions != originalAggregationExpressions)
            {
                var newSqlGroupingSelectExpression = new SqlGroupingSelectExpression(newKeyExpression, newElementExpression, newAggregationExpressions);
                return(newSqlGroupingSelectExpression);
            }
            return(this);
        }
    public void SetUp ()
    {
      _dataInfo = new StreamedScalarValueInfo (typeof (int));

      _resolvedElementExpressionReference = new SqlColumnDefinitionExpression (typeof (string), "q0", "element", false);
      _resolvedSelectProjection = new NamedExpression (
          null, 
          new AggregationExpression (typeof (int), _resolvedElementExpressionReference, AggregationModifier.Min));

      _associatedGroupingSelectExpression = new SqlGroupingSelectExpression (
          new NamedExpression ("key", Expression.Constant ("k")),
          new NamedExpression ("element", Expression.Constant ("e")));

      _resolvedJoinedGroupingSubStatement = SqlStatementModelObjectMother.CreateSqlStatement (_associatedGroupingSelectExpression);
      _resolvedJoinedGroupingTable = new SqlTable (
          new ResolvedJoinedGroupingTableInfo (
              "q1",
              _resolvedJoinedGroupingSubStatement,
              _associatedGroupingSelectExpression,
              "q0"), JoinSemantics.Inner);

      _simplifiableResolvedSqlStatement = new SqlStatement (
          _dataInfo,
          _resolvedSelectProjection,
          new[] { _resolvedJoinedGroupingTable },
          null,
          null,
          new Ordering[0],
          null,
          false,
          Expression.Constant (0),
          Expression.Constant (0));
      _simplifiableUnresolvedProjection = new AggregationExpression (
          typeof (int),
          new SqlTableReferenceExpression (_resolvedJoinedGroupingTable),
          AggregationModifier.Count);

      _stageMock = MockRepository.GenerateStrictMock<IMappingResolutionStage> ();
      _context = new MappingResolutionContext();

      _groupAggregateSimplifier = new GroupAggregateSimplifier (_stageMock, _context);
    }
    public Expression VisitSqlGroupingSelectExpression (SqlGroupingSelectExpression expression)
    {
      ArgumentUtility.CheckNotNull ("expression", expression);

      var referenceToKeyExpression = ResolveChildExpression (expression.KeyExpression);
      var referenceToElementExpression = ResolveChildExpression (expression.ElementExpression);
      var referenceToAggregationExpressions = expression.AggregationExpressions.Select (expr => ResolveChildExpression (expr));

      var newGroupingExpression = SqlGroupingSelectExpression.CreateWithNames (referenceToKeyExpression, referenceToElementExpression);
      foreach (var aggregationExpression in referenceToAggregationExpressions)
        newGroupingExpression.AddAggregationExpressionWithName (aggregationExpression);

      _context.AddGroupReferenceMapping (newGroupingExpression, _sqlTable);

      return newGroupingExpression;
    }
    protected override Expression VisitChildren (ExpressionTreeVisitor visitor)
    {
      ArgumentUtility.CheckNotNull ("visitor", visitor);

      var newKeyExpression = visitor.VisitExpression (KeyExpression);
      var newElementExpression = visitor.VisitExpression (ElementExpression);

      var originalAggregationExpressions = AggregationExpressions;
      var newAggregationExpressions = visitor.VisitAndConvert (originalAggregationExpressions, "VisitChildren");

      if (newKeyExpression != KeyExpression 
          || newElementExpression != ElementExpression 
          || newAggregationExpressions != originalAggregationExpressions)
      {
        var newSqlGroupingSelectExpression = new SqlGroupingSelectExpression (newKeyExpression, newElementExpression, newAggregationExpressions);
        return newSqlGroupingSelectExpression;
      }
      return this;
    }
 public override Expression VisitSqlGroupingSelectExpression (SqlGroupingSelectExpression expression)
 {
   throw new NotSupportedException (
       "This SQL generator does not support queries returning groupings that result from a GroupBy operator because SQL is not suited to "
       + "efficiently return "
       + "LINQ groupings. Use 'group into' and either return the items of the groupings by feeding them into an additional from clause, or perform "
       + "an aggregation on the groupings. "
       + Environment.NewLine
       + Environment.NewLine
       + "Eg., instead of: "
       + Environment.NewLine + "'from c in Cooks group c.ID by c.Name', "
       + Environment.NewLine + "write: "
       + Environment.NewLine + "'from c in Cooks group c.ID by c.Name into groupedCooks "
       + Environment.NewLine + " from c in groupedCooks select new { Key = groupedCooks.Key, Item = c }', "
       + Environment.NewLine + "or: "
       + Environment.NewLine + "'from c in Cooks group c.ID by c.Name into groupedCooks "
       + Environment.NewLine + " select new { Key = groupedCooks.Key, Count = groupedCooks.Count() }'.");
 }
    public Expression VisitSqlGroupingSelectExpression (SqlGroupingSelectExpression expression)
    {
      var newKeyExpression = ApplyValueContext (expression.KeyExpression);
      var newElementExpression = ApplyValueContext (expression.ElementExpression);
      var newAggregationExpressions = expression.AggregationExpressions
          .Select (ApplyValueContext)
          .ToArray();

      if (newKeyExpression != expression.KeyExpression
          || newElementExpression != expression.ElementExpression
          || !newAggregationExpressions.SequenceEqual (expression.AggregationExpressions))
        return _context.UpdateGroupingSelectAndAddMapping (expression, newKeyExpression, newElementExpression, newAggregationExpressions);

      return expression;
    }
    public void ResolveSubStatementReferenceExpression_CreatesSqlGroupingSelectExpressionWithNamedExpressions ()
    {
      var expression = new SqlGroupingSelectExpression (
          Expression.Constant ("key"), Expression.Constant ("element"), new[] { Expression.Constant ("aggregation") });
      var tableInfo = new ResolvedSubStatementTableInfo ("q0", SqlStatementModelObjectMother.CreateSqlStatement_Resolved (typeof (Cook)));
      var sqlTable = SqlStatementModelObjectMother.CreateSqlTable(typeof(Cook));

      var exprectedResult = new SqlGroupingSelectExpression (
          new NamedExpression ("key", Expression.Constant ("key")),
          new NamedExpression ("element", Expression.Constant ("element")),
          new[] { new NamedExpression ("a0", Expression.Constant ("aggregation")) });

      var result = SubStatementReferenceResolver.ResolveSubStatementReferenceExpression (expression, tableInfo, sqlTable, _context);

      SqlExpressionTreeComparer.CheckAreEqualTrees (result, exprectedResult);
      Assert.That (_context.GetReferencedGroupSource (((SqlGroupingSelectExpression) result)), Is.SameAs (sqlTable));
    }
    public void ResolveSubStatementReferenceExpression_CreatesSqlGroupingReferenceExpression_ForSqlGroupingSelectExpression ()
    {
      var groupingSelectExpression = new SqlGroupingSelectExpression (
          SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook), "key"),  
          new NamedExpression ("element", Expression.Constant (0)), 
          new[] { new NamedExpression ("a0", Expression.Constant (1)) });
      var sqlStatement = new SqlStatementBuilder (SqlStatementModelObjectMother.CreateSqlStatement_Resolved (typeof (Cook)))
      {
        SelectProjection = groupingSelectExpression,
        DataInfo = new StreamedSequenceInfo (typeof (IGrouping<int, int>[]), Expression.Constant (null, typeof (IGrouping<int, int>)))
      }.GetSqlStatement ();
      var tableInfo = new ResolvedSubStatementTableInfo ("q0", sqlStatement);
      var sqlTable = new SqlTable (tableInfo, JoinSemantics.Inner);

      var result = SubStatementReferenceResolver.ResolveSubStatementReferenceExpression (groupingSelectExpression, tableInfo, sqlTable, _context);

      Assert.That (result, Is.TypeOf (typeof (SqlGroupingSelectExpression)));

      var referencedKeyExpression = ((SqlGroupingSelectExpression) result).KeyExpression;
      var expectedReferencedKeyExpression = new NamedExpression("key", new SqlEntityReferenceExpression (
          typeof (Cook), 
          "q0", 
          null, 
          (SqlEntityExpression) groupingSelectExpression.KeyExpression));
      SqlExpressionTreeComparer.CheckAreEqualTrees (expectedReferencedKeyExpression, referencedKeyExpression);

      var referencedElementExpression = ((SqlGroupingSelectExpression) result).ElementExpression;
      var expectedReferencedElementExpression = new NamedExpression("element", new SqlColumnDefinitionExpression (typeof (int), "q0", "element", false));
      SqlExpressionTreeComparer.CheckAreEqualTrees (expectedReferencedElementExpression, referencedElementExpression);

      Assert.That (((SqlGroupingSelectExpression) result).AggregationExpressions.Count, Is.EqualTo (1));
      var referencedAggregationExpression = ((SqlGroupingSelectExpression) result).AggregationExpressions[0];
      var expectedReferencedAggregationExpression = new NamedExpression("a0", new SqlColumnDefinitionExpression (typeof (int), "q0", "a0", false));
      SqlExpressionTreeComparer.CheckAreEqualTrees (expectedReferencedAggregationExpression, referencedAggregationExpression);

      Assert.That (_context.GetReferencedGroupSource (((SqlGroupingSelectExpression) result)), Is.SameAs (sqlTable));
    }
    public void VisitSqlGroupingSelectExpression_WithoutAggregationExpressions ()
    {
      var groupingExpression = new SqlGroupingSelectExpression (Expression.Constant ("keyExpression"), Expression.Constant ("elementExpression"));

      SqlGeneratingSelectExpressionVisitor.GenerateSql (groupingExpression, _commandBuilder, _stageMock);

      Assert.That (_commandBuilder.GetCommandText (), Is.EqualTo ("@1"));
      Assert.That (_commandBuilder.GetCommandParameters ()[0].Value, Is.EqualTo ("keyExpression"));
    }
    public void ResolveTableInfo_GroupReferenceTableInfo ()
    {
      var sqlTable = SqlStatementModelObjectMother.CreateSqlTable (typeof (Cook));
      var groupingSelect = new SqlGroupingSelectExpression (
          Expression.MakeMemberAccess (new SqlTableReferenceExpression (sqlTable), typeof (Cook).GetProperty ("Name")),
          Expression.MakeMemberAccess (new SqlTableReferenceExpression (sqlTable), typeof (Cook).GetProperty ("ID")));
      var dataInfo = new StreamedSequenceInfo (
          typeof (IEnumerable<>).MakeGenericType (groupingSelect.Type), 
          Expression.Constant (null, groupingSelect.Type));
      var whereCondition = Expression.Constant (false);
      var groupByExpression = groupingSelect.KeyExpression;
      var groupingSubStatement = new SqlStatementBuilder
                                 {
                                     DataInfo = dataInfo,
                                     SelectProjection = groupingSelect,
                                     SqlTables = { sqlTable },
                                     WhereCondition = whereCondition,
                                     GroupByExpression = groupByExpression
                                 }.GetSqlStatement();
      var groupSource = SqlStatementModelObjectMother.CreateSqlTable (new ResolvedSubStatementTableInfo ("q0", groupingSubStatement));
      var tableInfo = new UnresolvedGroupReferenceTableInfo (groupSource);

      var expectedKeyViaElement = Expression.MakeMemberAccess (new SqlTableReferenceExpression (sqlTable), typeof (Cook).GetProperty ("Name"));
      var expectedKeyViaGroupSource = Expression.MakeMemberAccess (new SqlTableReferenceExpression (groupSource), groupSource.ItemType.GetProperty ("Key"));
      
      var expectedResultWhereCondition =
          Expression.OrElse (
              Expression.AndAlso (new SqlIsNullExpression (expectedKeyViaElement), new SqlIsNullExpression (expectedKeyViaGroupSource)),
              Expression.AndAlso (
                  Expression.AndAlso (new SqlIsNotNullExpression (expectedKeyViaElement), new SqlIsNotNullExpression (expectedKeyViaGroupSource)),
                  Expression.Equal (expectedKeyViaElement, expectedKeyViaGroupSource)));
      
      var fakeWhereCondition = Expression.Constant (false);
      _stageMock
          .Expect (mock => mock.ResolveWhereExpression (Arg<Expression>.Is.Anything, Arg.Is (_mappingResolutionContext)))
          .WhenCalled (mi => SqlExpressionTreeComparer.CheckAreEqualTrees (expectedResultWhereCondition, (Expression) mi.Arguments[0]))
          .Return (fakeWhereCondition);
      _stageMock.Replay();

      var result = ResolvingTableInfoVisitor.ResolveTableInfo (tableInfo, _resolverMock, _generator, _stageMock, _mappingResolutionContext);

      _stageMock.VerifyAllExpectations();

      Assert.That (result, Is.TypeOf (typeof (ResolvedJoinedGroupingTableInfo)));

      var castResult = ((ResolvedJoinedGroupingTableInfo) result);
      
      var resultGroupingSelector = castResult.AssociatedGroupingSelectExpression;
      Assert.That (resultGroupingSelector, Is.SameAs (groupingSelect));

      Assert.That (castResult.GroupSourceTableAlias, Is.EqualTo ("q0"));
      
      var resultSqlStatement = castResult.SqlStatement;

      Assert.That (resultSqlStatement.SqlTables, Is.EqualTo (groupingSubStatement.SqlTables));
      Assert.That (resultSqlStatement.Orderings, Is.Empty);
      Assert.That (resultSqlStatement.GroupByExpression, Is.Null);
      
      SqlExpressionTreeComparer.CheckAreEqualTrees (
          Expression.AndAlso (groupingSubStatement.WhereCondition, fakeWhereCondition), 
          resultSqlStatement.WhereCondition);

      var expectedResultSelectProjection =
          Expression.MakeMemberAccess (new SqlTableReferenceExpression (resultSqlStatement.SqlTables[0]), typeof (Cook).GetProperty ("ID"));
      SqlExpressionTreeComparer.CheckAreEqualTrees (expectedResultSelectProjection, resultSqlStatement.SelectProjection);

      Assert.That (resultSqlStatement.DataInfo, Is.TypeOf (typeof (StreamedSequenceInfo)));
      Assert.That (resultSqlStatement.DataInfo.DataType, Is.SameAs (typeof (IQueryable<int>)));

      var expectedItemExpression = resultSqlStatement.SelectProjection;
      SqlExpressionTreeComparer.CheckAreEqualTrees (expectedItemExpression, ((StreamedSequenceInfo) resultSqlStatement.DataInfo).ItemExpression);
    }
    public void ProcessNames_SqlGroupingSelectExpression ()
    {
      var keyExpression = new NamedExpression ("key", Expression.Constant ("key"));
      var elementExpression = new NamedExpression ("element", Expression.Constant ("element"));
      var aggregationExpression = new NamedExpression ("a0", Expression.Constant ("aggregation"));
      var groupingSelectExpression = new SqlGroupingSelectExpression (keyExpression, elementExpression, new[]{aggregationExpression});
      var expression = new NamedExpression ("outer", groupingSelectExpression);
      var sqlTable = SqlStatementModelObjectMother.CreateSqlTable (typeof (Cook));
      _context.AddGroupReferenceMapping (groupingSelectExpression, sqlTable);

      var expectedResult = new SqlGroupingSelectExpression (
          new NamedExpression ("outer_key", Expression.Constant ("key")), 
          new NamedExpression ("outer_element", Expression.Constant ("element")),
          new[]{new NamedExpression("outer_a0", Expression.Constant("aggregation"))});

      var result = _namedExpressionCombiner.ProcessNames (expression);

      SqlExpressionTreeComparer.CheckAreEqualTrees (result, expectedResult);
      Assert.That (_context.GetReferencedGroupSource (((SqlGroupingSelectExpression) result)), Is.SameAs (sqlTable));
    }
    public SqlGroupingSelectExpression UpdateGroupingSelectAndAddMapping (
        SqlGroupingSelectExpression expression, Expression newKey, Expression newElement, IEnumerable<Expression> aggregations)
    {
      ArgumentUtility.CheckNotNull ("expression", expression);
      ArgumentUtility.CheckNotNull ("newKey", newKey);
      ArgumentUtility.CheckNotNull ("newElement", newElement);
      ArgumentUtility.CheckNotNull ("aggregations", aggregations);

      var newSqlGroupingSelectExpression = expression.Update (newKey, newElement, aggregations);
      SqlTableBase tableForGroupingSelectExpression; 
      if(_groupReferenceMapping.TryGetValue(expression, out tableForGroupingSelectExpression))
        AddGroupReferenceMapping (newSqlGroupingSelectExpression, tableForGroupingSelectExpression);
      return newSqlGroupingSelectExpression;
    }
    public void ResolveMemberAccess_OnGroupingSelectExpression_StripsNames ()
    {
      var expression = new SqlGroupingSelectExpression (
          new NamedExpression ("k", Expression.Constant ("key")), 
          new NamedExpression ("e", Expression.Constant ("element")));
      var memberInfo = typeof (IGrouping<string, string>).GetProperty ("Key");

      var result = MemberAccessResolver.ResolveMemberAccess (expression, memberInfo, _resolverMock, _stageMock, _mappingResolutionContext);

      Assert.That (result, Is.SameAs (((NamedExpression) expression.KeyExpression).Expression));
    }
    public void VisitSqlGroupingSelectExpression_KeepsValueSemantics ()
    {
      var keyExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook));
      var elementExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook));
      var aggregateExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook));

      var expression = new SqlGroupingSelectExpression (keyExpression, elementExpression, new[] { aggregateExpression });
      var sqlTable = SqlStatementModelObjectMother.CreateSqlTable (typeof (Cook));
      _mappingResolutionContext.AddGroupReferenceMapping (expression, sqlTable);

      var result = _singleValueRequiredVisitor.VisitSqlGroupingSelectExpression (expression);

      Assert.That (result, Is.SameAs (expression));
      Assert.That (_mappingResolutionContext.GetReferencedGroupSource (((SqlGroupingSelectExpression) result)), Is.SameAs (sqlTable));
    }
    public void VisitSqlGroupingSelectExpression_VisitsChildren ()
    {
      var keyExpression = Expression.Constant (false);
      var elementExpression = Expression.Constant (false);
      var aggregateExpression = Expression.Constant (true);

      var expression = new SqlGroupingSelectExpression (keyExpression, elementExpression, new[] { aggregateExpression });
      var sqlTable = SqlStatementModelObjectMother.CreateSqlTable (typeof (Cook));
      _mappingResolutionContext.AddGroupReferenceMapping (expression, sqlTable);

      var result = (SqlGroupingSelectExpression) _singleValueRequiredVisitor.VisitSqlGroupingSelectExpression (expression);

      Assert.That (result, Is.Not.SameAs (expression));

      SqlExpressionTreeComparer.CheckAreEqualTrees (new SqlConvertedBooleanExpression (Expression.Constant (0)), result.KeyExpression);
      SqlExpressionTreeComparer.CheckAreEqualTrees (new SqlConvertedBooleanExpression (Expression.Constant (0)), result.ElementExpression);
      SqlExpressionTreeComparer.CheckAreEqualTrees (new SqlConvertedBooleanExpression (Expression.Constant (1)), result.AggregationExpressions[0]);
      Assert.That (_mappingResolutionContext.GetReferencedGroupSource (result), Is.SameAs (sqlTable));
    }