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)); }
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()); }
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)); }
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)); }
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))); }
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)); }
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); }
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); }
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)); }