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; }
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 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; }
protected override Expression VisitMemberExpression (MemberExpression expression) { ArgumentUtility.CheckNotNull ("expression", expression); var newInnerExpression = VisitExpression (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 VisitExpression (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 VisitExpression (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, VisitExpression (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 VisitExpression (tranformedExpression); } } } return base.VisitMemberExpression (expression); }
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); }
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)))); }