Example #1
0
        public void BuildSetOperationCombinedStatementsPart_UnionAll()
        {
            var setOperationCombinedStatement = new SetOperationCombinedStatement(SqlStatementModelObjectMother.CreateSqlStatement(), SetOperation.UnionAll);
            var sqlStatement = SqlStatementModelObjectMother.CreateMinimalSqlStatement(
                new SqlStatementBuilder
            {
                SetOperationCombinedStatements = { setOperationCombinedStatement }
            });

            _stageMock.Expect(mock => mock.GenerateTextForSqlStatement(_commandBuilder, setOperationCombinedStatement.SqlStatement))
            .WhenCalled(mi => ((SqlCommandBuilder)mi.Arguments[0]).Append("statement"));
            _stageMock.Replay();

            _generator.BuildSetOperationCombinedStatementsPart(sqlStatement, _commandBuilder);

            Assert.That(_commandBuilder.GetCommandText(), Is.EqualTo(" UNION ALL (statement)"));
            _stageMock.VerifyAllExpectations();
        }
Example #2
0
        public override void HandleResultOperator(
            TResultOperator 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);

            UpdateDataInfo(resultOperator, sqlStatementBuilder, sqlStatementBuilder.DataInfo);

            var source2 = GetSource2(resultOperator);
            var preparedSubStatement = stage.PrepareResultOperatorItemExpression(source2, context) as SqlSubStatementExpression;

            if (preparedSubStatement == null)
            {
                var message = string.Format(
                    "The '" + _operationName + "' operation is only supported for combining two query results, but a '{0}' was supplied as the "
                    + "second sequence: {1}",
                    source2.GetType().Name,
                    source2);
                throw new NotSupportedException(message);
            }

            var combinedStatement = new SetOperationCombinedStatement(preparedSubStatement.SqlStatement, _setOperation);

            sqlStatementBuilder.SetOperationCombinedStatements.Add(combinedStatement);

            // The set operators act as an IQuerySource, i.e., subsequent result operators can refer to its output.
            // When a result operator references the set operator's output, it should simply refer to the outer statement's select projection instead.
            AddMappingForItemExpression(context, sqlStatementBuilder.DataInfo, sqlStatementBuilder.SelectProjection);

            // In SQL, the set operators does not allow the input sequences to contain an "ORDER BY". Therefore, we'll remove them, if any, unless a TOP
            // expression is specified.
            if (sqlStatementBuilder.Orderings.Any() && sqlStatementBuilder.TopExpression == null)
            {
                sqlStatementBuilder.Orderings.Clear();
            }

            // For the second source, removal of unneeded orderings is already performed by PrepareResultOperatorItemExpression.
            Assertion.DebugAssert(!combinedStatement.SqlStatement.Orderings.Any() || combinedStatement.SqlStatement.TopExpression != null);

            // However, if an ORDER BY _is_ included together with a TOP, then the ORDER BY is allowed again as long as the whole set-combined statement is
            // moved to a substatement.
            // I.e., this is invalid:
            //   SELECT  [t0].[ID] AS [value] FROM [CookTable] AS [t0] WHERE ([t0].[FirstName] = 'Hugo')
            //   UNION (SELECT TOP (2) [t1].[ID] AS [value] FROM [CookTable] AS [t1] WHERE ([t1].[Name] = 'Boss') ORDER BY [t1].[ID] ASC)
            // but this is valid:
            // SELECT * FROM
            // (
            //   SELECT  [t0].[ID] AS [value] FROM [CookTable] AS [t0] WHERE ([t0].[FirstName] = 'Hugo')
            //   UNION (SELECT TOP (2) [t1].[ID] AS [value] FROM [CookTable] AS [t1] WHERE ([t1].[Name] = 'Boss') ORDER BY [t1].[ID] ASC)
            // ) AS q0

            if (sqlStatementBuilder.Orderings.Any() || combinedStatement.SqlStatement.Orderings.Any())
            {
                MoveCurrentStatementToSqlTable(
                    sqlStatementBuilder,
                    context,
                    ti => new SqlTable(ti, JoinSemantics.Inner),
                    stage,
                    OrderingExtractionPolicy.DoNotExtractOrderings);
            }
        }