diff --git a/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs b/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs index 87ade981..84bf3570 100644 --- a/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs +++ b/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs @@ -44,8 +44,8 @@ public CompiledExpression(TSqlFragment expression, FuncThe type of value that will be returned by the expression public static Type GetType(this TSqlFragment expr, ExpressionCompilationContext context, out DataTypeReference sqlType) { - var expression = ToExpression(expr, context, out sqlType, out _); - return expression.ReturnType; + var expression = ToExpression(expr, context, out _, out sqlType, out _); + return expression.Type; } /// @@ -56,8 +56,8 @@ public static Type GetType(this TSqlFragment expr, ExpressionCompilationContext /// A function that accepts an representing the context the expression is being evaluated in and returns the value of the expression public static Func Compile(this TSqlFragment expr, ExpressionCompilationContext context) { - var lambda = ToExpression(expr, context, out _, out var cacheKey); - var compiled = _cache.GetOrAdd(cacheKey, _ => new CompiledExpression(expr, Expression.Lambda>(Expr.Box(lambda.Body), lambda.Parameters).Compile())); + var lambda = ToExpression(expr, context, out var parameters, out _, out var cacheKey); + var compiled = _cache.GetOrAdd(cacheKey, _ => new CompiledExpression(expr, Expression.Lambda>(Expr.Box(lambda), parameters).Compile())); return eec => compiled.Compiled(eec, expr); } @@ -70,13 +70,13 @@ public static Func Compile(this TSqlFragment /// A function that accepts aan representing the context the expression is being evaluated in and returns the value of the expression public static Func Compile(this BooleanExpression b, ExpressionCompilationContext context) { - var lambda = ToExpression(b, context, out _, out var cacheKey); - var compiled = _boolCache.GetOrAdd(cacheKey, _ => new CompiledExpression(b, Expression.Lambda>(Expression.IsTrue(lambda.Body), lambda.Parameters).Compile())); + var lambda = ToExpression(b, context, out var parameters, out _, out var cacheKey); + var compiled = _boolCache.GetOrAdd(cacheKey, _ => new CompiledExpression(b, Expression.Lambda>(Expression.IsTrue(lambda), parameters).Compile())); return eec => compiled.Compiled(eec, b); } - private static LambdaExpression ToExpression(this TSqlFragment expr, ExpressionCompilationContext context, out DataTypeReference sqlType, out string cacheKey) + private static Expression ToExpression(this TSqlFragment expr, ExpressionCompilationContext context, out ParameterExpression[] parameters, out DataTypeReference sqlType, out string cacheKey) { var contextParam = Expression.Parameter(typeof(ExpressionExecutionContext)); var exprParam = Expression.Parameter(typeof(TSqlFragment)); @@ -168,7 +168,8 @@ private static LambdaExpression ToExpression(this TSqlFragment expr, ExpressionC } } - return Expression.Lambda(expression, contextParam, exprParam); + parameters = new[] { contextParam, exprParam }; + return expression; } private static Expression InvokeSubExpression(this TParent parent, Func child, Expression> subExpressionSelector, ExpressionCompilationContext context, ParameterExpression contextParam, ParameterExpression exprParam, out DataTypeReference sqlType, out string cacheKey) @@ -176,7 +177,7 @@ private static Expression InvokeSubExpression(this TParent pare where TChild : TSqlFragment { // Build an expression to invoke the child expression from within the context of the parent expression - var expr = child(parent).ToExpression(context, out sqlType, out cacheKey); + var expr = child(parent).ToExpression(context, out var parameters, out sqlType, out cacheKey); if (!(subExpressionSelector is LambdaExpression lambda) || !(lambda.Body is MemberExpression memberAccessor) || @@ -185,7 +186,7 @@ private static Expression InvokeSubExpression(this TParent pare var subExpr = Expression.Property(Expression.Convert(exprParam, prop.DeclaringType), prop); - return Expression.Invoke(expr, contextParam, subExpr); + return Expression.Invoke(Expression.Lambda(expr, parameters), contextParam, subExpr); } private static Expression InvokeSubExpression(this TParent parent, Func child, Expression> subExpressionSelector, int index, ExpressionCompilationContext context, ParameterExpression contextParam, ParameterExpression exprParam, out DataTypeReference sqlType, out string cacheKey) @@ -193,11 +194,11 @@ private static Expression InvokeSubExpression(this TParent pare where TChild : TSqlFragment { // Build an expression to invoke the child expression from within the context of the parent expression - var expr = child(parent).ToExpression(context, out sqlType, out cacheKey); + var expr = child(parent).ToExpression(context, out var parameters, out sqlType, out cacheKey); var subExpr = Expression.Invoke(subExpressionSelector, Expression.Convert(exprParam, typeof(TParent)), Expression.Constant(index)); - return Expression.Invoke(expr, contextParam, subExpr); + return Expression.Invoke(Expression.Lambda(expr, parameters), contextParam, subExpr); } private static Expression ToExpression(ColumnReferenceExpression col, ExpressionCompilationContext context, ParameterExpression contextParam, ParameterExpression exprParam, out DataTypeReference sqlType, out string cacheKey)