示例#1
0
        public override void HandleResultOperator(
            GroupResultOperator resultOperator,
            SqlStatementBuilder sqlStatementBuilder,
            UniqueIdentifierGenerator generator,
            ISqlPreparationStage stage,
            ISqlPreparationContext context)
        {
            ArgumentUtility.CheckNotNull("resultOperator", resultOperator);
            ArgumentUtility.CheckNotNull("sqlStatementBuilder", sqlStatementBuilder);
            ArgumentUtility.CheckNotNull("generator", generator);
            ArgumentUtility.CheckNotNull("stage", stage);
            ArgumentUtility.CheckNotNull("context", context);

            EnsureNoTopExpression(sqlStatementBuilder, generator, stage, context);
            EnsureNoGroupExpression(sqlStatementBuilder, generator, stage, context);
            EnsureNoDistinctQuery(sqlStatementBuilder, generator, stage, context);
            UpdateDataInfo(resultOperator, sqlStatementBuilder, sqlStatementBuilder.DataInfo);

            var preparedKeySelector = stage.PrepareResultOperatorItemExpression(resultOperator.KeySelector, context);

            preparedKeySelector = HandlePotentialConstantExpression(preparedKeySelector);
            preparedKeySelector = HandlePotentialSubStatementExpression(preparedKeySelector, sqlStatementBuilder, generator);

            var preparedElementSelector = stage.PrepareResultOperatorItemExpression(resultOperator.ElementSelector, context);

            sqlStatementBuilder.GroupByExpression = preparedKeySelector;
            sqlStatementBuilder.SelectProjection  = SqlGroupingSelectExpression.CreateWithNames(preparedKeySelector, preparedElementSelector);
        }
示例#2
0
        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)))));
        }
示例#3
0
        public void AddGroupReferenceMapping(SqlGroupingSelectExpression groupingSelectExpression, SqlTableBase sqlTable)
        {
            ArgumentUtility.CheckNotNull("groupingSelectExpression", groupingSelectExpression);
            ArgumentUtility.CheckNotNull("sqlTable", sqlTable);

            _groupReferenceMapping[groupingSelectExpression] = sqlTable;
        }
示例#4
0
 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);
 }
示例#5
0
        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"));
        }
示例#6
0
        public virtual Expression VisitSqlGroupingSelect(SqlGroupingSelectExpression expression)
        {
            ArgumentUtility.CheckNotNull("expression", expression);

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

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

            return(expression);
        }
示例#7
0
        public Expression VisitSqlGroupingSelect(SqlGroupingSelectExpression expression)
        {
            ArgumentUtility.CheckNotNull("expression", expression);

            // Scenario: grouping.Key
            Assertion.DebugAssert(_memberInfo.Equals(expression.Type.GetProperty("Key")));

            // No problem, just use the KeyExpression (without a name, we don't care about the original name of the expression when we resolve members).

            return(_context.RemoveNamesAndUpdateMapping(expression.KeyExpression));
        }
示例#8
0
        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 CreateWithNames()
        {
            var result = SqlGroupingSelectExpression.CreateWithNames(_keyExpression, _elementExpression);

            var expectedKeyExpression = new NamedExpression("key", _keyExpression);

            SqlExpressionTreeComparer.CheckAreEqualTrees(expectedKeyExpression, result.KeyExpression);

            var expectedElementExpression = new NamedExpression("element", _elementExpression);

            SqlExpressionTreeComparer.CheckAreEqualTrees(expectedElementExpression, result.ElementExpression);
        }
        public ResolvedJoinedGroupingTableInfo(
            string tableAlias,
            SqlStatement sqlStatement,
            SqlGroupingSelectExpression associatedGroupingSelectExpression,
            string groupSourceTableAlias)
            : base(tableAlias, sqlStatement)
        {
            ArgumentUtility.CheckNotNull("associatedGroupingSelectExpression", associatedGroupingSelectExpression);
            ArgumentUtility.CheckNotNull("groupSourceTableAlias", groupSourceTableAlias);

            _associatedGroupingSelectExpression = associatedGroupingSelectExpression;
            _groupSourceTableAlias = groupSourceTableAlias;
        }
        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 });
        }
    public ResolvedJoinedGroupingTableInfo (
        string tableAlias, 
        SqlStatement sqlStatement, 
        SqlGroupingSelectExpression associatedGroupingSelectExpression,
        string groupSourceTableAlias)
      : base (tableAlias, sqlStatement)
    {
      ArgumentUtility.CheckNotNull ("associatedGroupingSelectExpression", associatedGroupingSelectExpression);
      ArgumentUtility.CheckNotNull ("groupSourceTableAlias", groupSourceTableAlias);

      _associatedGroupingSelectExpression = associatedGroupingSelectExpression;
      _groupSourceTableAlias = groupSourceTableAlias;
    }
示例#13
0
        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}'.", groupingSelectExpression);

            throw new InvalidOperationException(message);
        }
示例#14
0
        public void VisitSqlGroupingSelectExpression_WithAggregationExpressions_AndNames()
        {
            var groupingExpression = SqlGroupingSelectExpression.CreateWithNames(Expression.Constant("keyExpression"), Expression.Constant("elementExpression"));

            groupingExpression.AddAggregationExpressionWithName(Expression.Constant("aggregation1"));
            groupingExpression.AddAggregationExpressionWithName(Expression.Constant("aggregation2"));

            SqlGeneratingSelectExpressionVisitor.GenerateSql(groupingExpression, _commandBuilder, _stageMock);

            Assert.That(_commandBuilder.GetCommandText(), Is.EqualTo("@1 AS [key], @2 AS [a0], @3 AS [a1]"));
            Assert.That(_commandBuilder.GetCommandParameters()[0].Value, Is.EqualTo("keyExpression"));
            Assert.That(_commandBuilder.GetCommandParameters()[1].Value, Is.EqualTo("aggregation1"));
            Assert.That(_commandBuilder.GetCommandParameters()[2].Value, Is.EqualTo("aggregation2"));
        }
示例#15
0
        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 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 Expression VisitSqlGroupingSelect(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);
        }
示例#18
0
 public override Expression VisitSqlGroupingSelect(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() }'.");
 }
示例#19
0
        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 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);
        }
示例#21
0
        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));
        }
示例#22
0
        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);
        }
示例#23
0
        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 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 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);
        }