Example #1
0
        private SqlTable CreateSqlCompatibleSubStatementTable(
            SqlStatement originalStatement,
            Expression newSelectProjection,
            Func <ITableInfo, SqlTable> tableCreator)
        {
            // create a new statement equal to the original one, but with the tuple as its select projection
            var builder = new SqlStatementBuilder(originalStatement)
            {
                SelectProjection = newSelectProjection
            };

            builder.RecalculateDataInfo(originalStatement.SelectProjection);

            // clear orderings unless required for TopExpression
            if (originalStatement.TopExpression == null)
            {
                builder.Orderings.Clear();
            }

            var newSqlStatement = builder.GetSqlStatement();

            // put new statement into a sub-statement table
            var subStatementTableInfo = new ResolvedSubStatementTableInfo(_uniqueIdentifierGenerator.GetUniqueIdentifier("q"), newSqlStatement);

            return(tableCreator(subStatementTableInfo));
        }
        private SubStatementWithRowNumber CreateSubStatementWithRowNumber(
            SqlStatementBuilder sqlStatementBuilder,
            UniqueIdentifierGenerator generator,
            ISqlPreparationStage stage,
            ISqlPreparationContext context)
        {
            var originalSelectProjection = sqlStatementBuilder.SelectProjection;

            IncludeRowNumberInSelectProjection(sqlStatementBuilder, stage, context);

            // Orderings are not allowed in SQL substatements unless a TOP expression is present
            if (sqlStatementBuilder.TopExpression == null)
            {
                sqlStatementBuilder.Orderings.Clear();
            }

            sqlStatementBuilder.RecalculateDataInfo(originalSelectProjection);
            // No NamedExpression required here because the row number tuple's items already have named members
            var newSqlStatement = sqlStatementBuilder.GetStatementAndResetBuilder();

            var tableInfo = new ResolvedSubStatementTableInfo(generator.GetUniqueIdentifier("q"), newSqlStatement);
            var sqlTable  = new SqlTable(tableInfo, JoinSemantics.Inner);

            var originalProjectionSelector = Expression.MakeMemberAccess(
                new SqlTableReferenceExpression(sqlTable),
                newSqlStatement.SelectProjection.Type.GetProperty("Key"));
            var rowNumberSelector = Expression.MakeMemberAccess(
                new SqlTableReferenceExpression(sqlTable),
                newSqlStatement.SelectProjection.Type.GetProperty("Value"));

            return(new SubStatementWithRowNumber(sqlTable, originalProjectionSelector, rowNumberSelector));
        }
Example #3
0
        protected virtual SqlStatement ResolveSqlStatement(SqlStatement sqlStatement)
        {
            ArgumentUtility.CheckNotNull("sqlStatement", sqlStatement);

            foreach (var sqlTable in sqlStatement.SqlTables)
            {
                sqlTable.Accept(this);
            }

            var sqlStatementBuilder = new SqlStatementBuilder(sqlStatement);

            var previousSelectProjection = sqlStatementBuilder.SelectProjection;

            sqlStatementBuilder.SelectProjection = ResolveSelectProjection(sqlStatementBuilder.SelectProjection, sqlStatementBuilder);
            sqlStatementBuilder.RecalculateDataInfo(previousSelectProjection);

            if (sqlStatementBuilder.GroupByExpression != null)
            {
                sqlStatementBuilder.GroupByExpression = ResolveGroupByExpression(sqlStatementBuilder.GroupByExpression);
            }

            if (sqlStatementBuilder.WhereCondition != null)
            {
                sqlStatementBuilder.WhereCondition = ResolveWhereCondition(sqlStatementBuilder.WhereCondition);
            }

            if (sqlStatementBuilder.TopExpression != null)
            {
                sqlStatementBuilder.TopExpression = ResolveTopExpression(sqlStatementBuilder.TopExpression);
            }

            if (sqlStatementBuilder.Orderings.Count > 0)
            {
                for (int i = 0; i < sqlStatementBuilder.Orderings.Count; ++i)
                {
                    var resolvedOrderingExpression = _stage.ResolveOrderingExpression(sqlStatementBuilder.Orderings[i].Expression, _context);
                    if (resolvedOrderingExpression != sqlStatementBuilder.Orderings[i].Expression)
                    {
                        sqlStatementBuilder.Orderings[i] = new Ordering(resolvedOrderingExpression, sqlStatementBuilder.Orderings[i].OrderingDirection);
                    }
                }
            }

            for (int i = 0; i < sqlStatement.SetOperationCombinedStatements.Count; i++)
            {
                var combinedStatement    = sqlStatement.SetOperationCombinedStatements[i];
                var resolvedSqlStatement = _stage.ResolveSqlStatement(combinedStatement.SqlStatement, _context);
                if (!Equals(resolvedSqlStatement, combinedStatement.SqlStatement))
                {
                    sqlStatementBuilder.SetOperationCombinedStatements[i] = new SetOperationCombinedStatement(
                        resolvedSqlStatement,
                        combinedStatement.SetOperation);
                }
            }

            return(sqlStatementBuilder.GetSqlStatement());
        }
Example #4
0
        public void RecalculateDataInfo_UnchangedProjectionType_SameDataInfo()
        {
            var statementBuilder = new SqlStatementBuilder();

            var previousSelectProjection = Expression.Constant("test");
            var originalDataInfo         = new StreamedSingleValueInfo(typeof(string), false);

            statementBuilder.DataInfo         = originalDataInfo;
            statementBuilder.SelectProjection = new SqlColumnDefinitionExpression(typeof(string), "c", "Length", false);

            statementBuilder.RecalculateDataInfo(previousSelectProjection);

            Assert.That(statementBuilder.DataInfo, Is.SameAs(originalDataInfo));
        }
Example #5
0
        public void RecalculateDataInfo_WithOtherDataInfo_ReturnsSameDataInfo()
        {
            var statementBuilder = new SqlStatementBuilder();

            var previousSelectProjection = Expression.Constant("test");
            var originalDataInfo         = new TestStreamedValueInfo(typeof(string));

            statementBuilder.DataInfo         = originalDataInfo;
            statementBuilder.SelectProjection = new SqlColumnDefinitionExpression(typeof(int), "c", "Length", false);

            statementBuilder.RecalculateDataInfo(previousSelectProjection);

            Assert.That(statementBuilder.DataInfo, Is.SameAs(originalDataInfo));
        }
Example #6
0
        public void RecalculateDataInfo_StreamedScalarValueInfo_ReturnsSameDataInfo()
        {
            var statementBuilder = new SqlStatementBuilder();

            var previousSelectProjection = Expression.Constant("test");

            statementBuilder.DataInfo         = new StreamedScalarValueInfo(typeof(string));
            statementBuilder.SelectProjection = new SqlColumnDefinitionExpression(typeof(int), "c", "Length", false);

            statementBuilder.RecalculateDataInfo(previousSelectProjection);

            Assert.That(statementBuilder.DataInfo, Is.TypeOf(typeof(StreamedScalarValueInfo)));
            Assert.That(((StreamedScalarValueInfo)statementBuilder.DataInfo).DataType, Is.EqualTo(typeof(string)));
        }
Example #7
0
        public void RecalculateDataInfo_StreamedSequenceInfo()
        {
            var statementBuilder = new SqlStatementBuilder();

            var previousSelectProjection = Expression.Constant(typeof(Restaurant));

            statementBuilder.DataInfo         = new StreamedSequenceInfo(typeof(IQueryable <>).MakeGenericType(typeof(Restaurant)), Expression.Constant(new Restaurant()));
            statementBuilder.SelectProjection = new SqlColumnDefinitionExpression(typeof(string), "c", "Name", false);

            statementBuilder.RecalculateDataInfo(previousSelectProjection);

            Assert.That(statementBuilder.DataInfo, Is.TypeOf(typeof(StreamedSequenceInfo)));
            Assert.That(((StreamedSequenceInfo)statementBuilder.DataInfo).DataType, Is.EqualTo(typeof(IQueryable <>).MakeGenericType(typeof(string))));
        }
        public ITableInfo VisitUnresolvedGroupReferenceTableInfo(UnresolvedGroupReferenceTableInfo tableInfo)
        {
            var groupSourceSubStatementTableInfo = tableInfo.ReferencedGroupSource.GetResolvedTableInfo() as ResolvedSubStatementTableInfo;

            if (groupSourceSubStatementTableInfo == null)
            {
                var message = string.Format(
                    "This SQL generator only supports sequences in from expressions if they are members of an entity or if they come from a GroupBy operator. "
                    + "Sequence: '{0}'", tableInfo);
                throw new NotSupportedException(message);
            }

            var groupingSelectExpression = groupSourceSubStatementTableInfo.SqlStatement.SelectProjection as SqlGroupingSelectExpression;

            if (groupingSelectExpression == null)
            {
                throw new NotSupportedException(
                          "When a sequence retrieved by a subquery is used in a from expression, the subquery must end with a GroupBy operator.");
            }

            var elementSelectingStatementBuilder = new SqlStatementBuilder(groupSourceSubStatementTableInfo.SqlStatement)
            {
                GroupByExpression = null
            };

            var currentKeyExpression = Expression.MakeMemberAccess(
                new SqlTableReferenceExpression(tableInfo.ReferencedGroupSource),
                groupingSelectExpression.Type.GetProperty("Key"));

            var groupKeyJoinCondition = _stage.ResolveWhereExpression(
                Expression.OrElse(
                    Expression.AndAlso(new SqlIsNullExpression(groupingSelectExpression.KeyExpression), new SqlIsNullExpression(currentKeyExpression)),
                    Expression.AndAlso(
                        Expression.AndAlso(
                            new SqlIsNotNullExpression(groupingSelectExpression.KeyExpression),
                            new SqlIsNotNullExpression(currentKeyExpression)),
                        Expression.Equal(groupingSelectExpression.KeyExpression, currentKeyExpression))),
                _context);

            elementSelectingStatementBuilder.AddWhereCondition(groupKeyJoinCondition);

            elementSelectingStatementBuilder.SelectProjection = groupingSelectExpression.ElementExpression;
            elementSelectingStatementBuilder.RecalculateDataInfo(groupingSelectExpression);

            return(new ResolvedJoinedGroupingTableInfo(
                       _generator.GetUniqueIdentifier("q"),
                       elementSelectingStatementBuilder.GetSqlStatement(),
                       groupingSelectExpression,
                       groupSourceSubStatementTableInfo.TableAlias));
        }
Example #9
0
        private Expression CheckAndSimplifyEntityWithinSubStatement(SqlSubStatementExpression sqlSubStatementExpression)
        {
            var newSelectProjection = ResolvePotentialEntity(sqlSubStatementExpression.SqlStatement.SelectProjection);

            if (newSelectProjection != sqlSubStatementExpression.SqlStatement.SelectProjection)
            {
                var newSubStatement = new SqlStatementBuilder(sqlSubStatementExpression.SqlStatement)
                {
                    SelectProjection = newSelectProjection
                };
                newSubStatement.RecalculateDataInfo(sqlSubStatementExpression.SqlStatement.SelectProjection);

                return(newSubStatement.GetSqlStatement().CreateExpression());
            }

            return(sqlSubStatementExpression);
        }
Example #10
0
        public SqlStatement VisitSqlStatement(SqlStatement sqlStatement, SqlExpressionContext expressionContext)
        {
            ArgumentUtility.CheckNotNull("sqlStatement", sqlStatement);

            if (expressionContext == SqlExpressionContext.PredicateRequired)
            {
                throw new InvalidOperationException("A SqlStatement cannot be used as a predicate.");
            }

            var statementBuilder = new SqlStatementBuilder(sqlStatement);

            var newSelectProjection = _stage.ApplyContext(sqlStatement.SelectProjection, expressionContext, _mappingResolutionContext);

            statementBuilder.SelectProjection = newSelectProjection;
            statementBuilder.RecalculateDataInfo(sqlStatement.SelectProjection);

            var newSqlStatement = statementBuilder.GetSqlStatement();

            return(newSqlStatement.Equals(sqlStatement) ? sqlStatement : newSqlStatement);
        }
Example #11
0
        protected override Expression VisitMember(MemberExpression expression)
        {
            ArgumentUtility.CheckNotNull("expression", expression);

            var newInnerExpression = Visit(expression.Expression);

            var innerExpressionAsSqlCaseExpression = newInnerExpression as SqlCaseExpression;

            if (innerExpressionAsSqlCaseExpression != null)
            {
                var originalCases    = innerExpressionAsSqlCaseExpression.Cases;
                var originalElseCase = innerExpressionAsSqlCaseExpression.ElseCase;
                var newCases         = originalCases.Select(c => new SqlCaseExpression.CaseWhenPair(c.When, Expression.MakeMemberAccess(c.Then, expression.Member)));
                var newElseCase      = originalElseCase != null?Expression.MakeMemberAccess(originalElseCase, expression.Member) : null;

                // If there is no else case, ensure that the resulting type is nullable
                var caseExpressionType =
                    newElseCase == null && expression.Type.IsValueType && Nullable.GetUnderlyingType(expression.Type) == null
                ? typeof(Nullable <>).MakeGenericType(expression.Type)
                : expression.Type;
                var newSqlCaseExpression = new SqlCaseExpression(caseExpressionType, newCases, newElseCase);
                return(Visit(newSqlCaseExpression));
            }

            if (newInnerExpression.NodeType == ExpressionType.Coalesce)
            {
                var innerExpressionAsBinaryExpression = (BinaryExpression)newInnerExpression;
                var newConditionalExpression          = Expression.Condition(
                    new SqlIsNotNullExpression(innerExpressionAsBinaryExpression.Left),
                    Expression.MakeMemberAccess(innerExpressionAsBinaryExpression.Left, expression.Member),
                    Expression.MakeMemberAccess(innerExpressionAsBinaryExpression.Right, expression.Member));
                return(Visit(newConditionalExpression));
            }

            var innerExpressionAsSqlSubStatementExpression = newInnerExpression as SqlSubStatementExpression;

            if (innerExpressionAsSqlSubStatementExpression != null)
            {
                var sqlStatementBuilder = new SqlStatementBuilder(innerExpressionAsSqlSubStatementExpression.SqlStatement);
                var namedExpression     = (NamedExpression)sqlStatementBuilder.SelectProjection;
                sqlStatementBuilder.SelectProjection = new NamedExpression(
                    namedExpression.Name, Visit(Expression.MakeMemberAccess(namedExpression.Expression, expression.Member)));
                sqlStatementBuilder.RecalculateDataInfo(innerExpressionAsSqlSubStatementExpression.SqlStatement.SelectProjection);
                return(new SqlSubStatementExpression(sqlStatementBuilder.GetSqlStatement()));
            }

            var memberAsPropertyInfo = expression.Member as PropertyInfo;

            if (memberAsPropertyInfo != null)
            {
                var methodInfo = memberAsPropertyInfo.GetGetMethod();
                if (methodInfo != null)
                {
                    var methodCallExpression = Expression.Call(expression.Expression, methodInfo);
                    var tranformer           = _methodCallTransformerProvider.GetTransformer(methodCallExpression);
                    if (tranformer != null)
                    {
                        var tranformedExpression = tranformer.Transform(methodCallExpression);
                        return(Visit(tranformedExpression));
                    }
                }
            }
            return(base.VisitMember(expression));
        }