internal static IObservable <TResult> ToTemporalObservable <TKey, TPayload, TResult>( this IStreamable <PartitionKey <TKey>, TPayload> stream, Expression <Func <TKey, long, long, TPayload, TResult> > constructor, QueryContainer container, string identifier) { Invariant.IsNotNull(stream, nameof(stream)); if (stream is IFusibleStreamable <PartitionKey <TKey>, TPayload> f && f.CanFuseEgressObservable) { if (stream.Properties.IsConstantDuration) { Expression <Func <PartitionKey <TKey>, TKey> > lower = (o) => o.Key; var newBody = ParameterSubstituter.Replace(constructor.Parameters[0], lower.Body, constructor.Body); var newFunc = Expression.Lambda <Func <long, long, TPayload, PartitionKey <TKey>, TResult> >( newBody, constructor.Parameters[1], constructor.Parameters[2], constructor.Parameters[3], lower.Parameters[0]); return(f.FuseEgressObservable(newFunc, container, identifier)); } } return(new PartitionedIntervalObservable <TKey, TPayload, TResult>(stream.ToEndEdgeFreeStream(), constructor, container, identifier)); }
public void Can_Parse_NHibernate_Log_Message_With_More_Than_Nine_Parameters() { var sql = @" select TOP (@p0) T.* from [Transaction] where (Code in (@p1, @p2, @p3 , @p4 , @p5 , @p6 , @p7 , @p8 , @p9 , @p10 , @p11 , @p12, @p13)); @p0 = 100 [Type: Int32 (0)], @p1 = 'A' [Type: String (1)], @p2 = 'B' [Type: String (2)], @p3 = 'C' [Type: String (3)], @p4 = 'D' [Type: String (4)], @p5 = 'E' [Type: String (5)], @p6 = 'F' [Type: String (6)], @p7 = 'G' [Type: String (7)], @p8 = 'H' [Type: String (8)], @p9 = 'I' [Type: String (9)], @p10 = 'J' [Type: String (10)], @p11 = 'K' [Type: String (11)], @p12 = 'L' [Type: String (12)], @p13 = 'M' [Type: String (13)] "; // cleanup test data to match 'real' input, while allowing it to be readable above sql = sql.Replace(Environment.NewLine, " "); // // Exercise ParameterSubstituter builder = new ParameterSubstituter(); var splitSql = builder.UpdateParamsWithValues(sql); var statement = ParserFactory.Execute <SelectStatement>(splitSql).First(); // Verify outcome Assert.IsNotNull(statement); Assert.AreEqual("[Transaction]", statement.From.First().Name); Assert.AreEqual("(100)", statement.Top.Expression.Value); Assert.AreEqual("(Code IN ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M'))", statement.Where.Value); }
public void Can_Parse_NHibernate_Log_Message_With_Parameters() { var sql = @" select TOP (@p0) T.Name from [Transaction] where (T.Code in (@p1, @p2)); @p0 = 100 [Type: Int32 (0)], @p1 = 'AA BB' [Type: String (4000)], @p2 = 'CCC' [Type: String (4000)] "; // cleanup test data to match 'real' input, while allowing it to be readable above sql = sql.Replace(Environment.NewLine, " "); // // Exercise ParameterSubstituter builder = new ParameterSubstituter(); var splitSql = builder.UpdateParamsWithValues(sql); var statement = ParserFactory.Execute <SelectStatement>(splitSql).First(); // Verify outcome Assert.IsNotNull(statement); Assert.AreEqual("[Transaction]", statement.From.First().Name); Assert.AreEqual("(100)", statement.Top.Expression.Value); Assert.AreEqual("(T.Code IN ('AA BB', 'CCC'))", statement.Where.Value); }
public override Expression Expand(MethodCallExpression methodCallExpression, IExpressionEvaluator evaluator) { // The first argument of any 'Eval' call is always the expression to be evaluated. // Its retrival must not throw exceptions (unless in an invalid subtree). var lambda = (LambdaExpression)evaluator.Evaluate(methodCallExpression.Arguments[0]); var substituted = ParameterSubstituter.SubstituteParameter( lambda, methodCallExpression.Arguments.Skip(1)); return(substituted); }
public FuseModule FuseSelect <TPayload, TResult>(Expression <Func <long, TPayload, TResult> > selector) { if (this.expressions.Count == 0) { this.expressions.Add( new ExpressionProfile { category = ExpressionCategory.Select, hasStartEdge = true, inputType = typeof(TPayload), outputType = typeof(TResult), expression = selector }); return(this); } var prev = this.expressions[this.expressions.Count - 1]; switch (prev.category) { case ExpressionCategory.Select: { IEnumerable <ParameterExpression> parameters = prev.expression.Parameters; var body = ParameterSubstituter.Replace(selector.Parameters[1], prev.expression.Body, selector.Body); if (prev.category == ExpressionCategory.Select && prev.hasStartEdge) { body = ParameterSubstituter.Replace(selector.Parameters[0], prev.expression.Parameters[0], body); } else { parameters = selector.Parameters[0].Yield().Concat(parameters); } prev.outputType = typeof(TResult); prev.expression = Expression.Lambda(body, parameters); break; } default: { this.expressions.Add(new ExpressionProfile { category = ExpressionCategory.Select, hasStartEdge = true, inputType = typeof(TPayload), outputType = typeof(TResult), expression = selector }); break; } } return(this); }
LambdaExpression unquote(LambdaExpression quotedLambda) { if (parameters.Count == 0) { return(quotedLambda); } else { return((LambdaExpression)ParameterSubstituter.SubstituteParameter( quotedLambda, parameters.ToDictionary(kvp => kvp.Key, kvp => (Expression)Expression.Constant(kvp.Value)))); } }
public IDisposable Subscribe(IObserver <TOutput> observer) { Expression <Action <TOutput> > onNext = (o) => observer.OnNext(o); var onNextResultBody = onNext.ReplaceParametersInBody(this.resultConstructor.Body); var onNextResult = Expression.Lambda <Action <long, long, TResult, TKey> >( onNextResultBody, this.resultConstructor.Parameters); var onNextFused = this.fuseModule.Coalesce <TPayload, TResult, TKey>(onNextResult); Expression onNextPunctuation; var baseType = typeof(TOutput); if (baseType.GetTypeInfo().IsGenericType) { baseType = baseType.GetGenericTypeDefinition(); } onNextPunctuation = baseType == typeof(StreamEvent <>) || baseType == typeof(PartitionedStreamEvent <,>) ? Expression.IfThenElse( Expression.Equal(onNextFused.Parameters[1], Expression.Constant(long.MinValue)), onNextResultBody, onNextFused.Body) : Expression.IfThen( Expression.NotEqual(onNextFused.Parameters[1], Expression.Constant(long.MinValue)), onNextFused.Body); var onNextReplacedEdges = ParameterSubstituter.Replace( onNextFused.Parameters[0], this.startEdgeExtractor.Body, onNextFused.Parameters[1], this.endEdgeExtractor.Body, onNextPunctuation); var onNextReplacedValues = ParameterSubstituter.Replace( onNextFused.Parameters[2], this.payloadExtractor.Body, onNextFused.Parameters[3], this.keyExtractor.Body, onNextReplacedEdges); var onNextFinal = Expression.Lambda <Action <TInput> >(onNextReplacedValues, this.inputParameter); var pipe = new FusedObservablePipe <TInput>(observer.OnCompleted, observer.OnError, onNextFinal.Compile(), this.ingressIdentifier); if (this.container != null) { this.container.RegisterEgressPipe(this.egressIdentifier, pipe); } return(this.observable.Subscribe(pipe)); }
public FuseModule FuseSelectMany <TPayload, TResult>(Expression <Func <TPayload, IEnumerable <TResult> > > selector) { if (this.expressions.Count == 0) { this.expressions.Add(new ExpressionProfile { category = ExpressionCategory.SelectMany, inputType = typeof(TPayload), outputType = typeof(TResult), expression = selector }); return(this); } var prev = this.expressions[this.expressions.Count - 1]; switch (prev.category) { case ExpressionCategory.Select: { var body = ParameterSubstituter.Replace(selector.Parameters[0], prev.expression.Body, selector.Body); prev.category = ExpressionCategory.SelectMany; prev.outputType = typeof(TResult); prev.expression = Expression.Lambda(body, prev.expression.Parameters); break; } default: { this.expressions.Add(new ExpressionProfile { category = ExpressionCategory.SelectMany, inputType = typeof(TPayload), outputType = typeof(TResult), expression = selector }); break; } } return(this); }
public FuseModule FuseWhere <TPayload>(Expression <Func <TPayload, bool> > expression) { if (this.expressions.Count == 0 || this.expressions[this.expressions.Count - 1].category != ExpressionCategory.Where) { this.expressions.Add(new ExpressionProfile { category = ExpressionCategory.Where, inputType = typeof(TPayload), outputType = typeof(TPayload), expression = expression }); return(this); } var prev = this.expressions[this.expressions.Count - 1]; var parameter = prev.expression.Parameters[0]; var replaced = ParameterSubstituter.Replace(expression.Parameters[0], parameter, expression.Body); prev.expression = Expression.Lambda <Func <TPayload, bool> >(Expression.And(prev.expression.Body, replaced), parameter); return(this); }
public void Can_Parse_NHibernate_Log_Message_With_DateTime_Parameter() { var sql = @" select T.Name from [Transaction] where Start > @p0; @p0 = 23/05/2011 2:51:54 PM [Type: DateTime (0)] "; // cleanup test data to match 'real' input, while allowing it to be readable above sql = sql.Replace(Environment.NewLine, " "); // // Exercise ParameterSubstituter builder = new ParameterSubstituter(); var splitSql = builder.UpdateParamsWithValues(sql); var statement = ParserFactory.Execute <SelectStatement>(splitSql).First(); // Verify outcome Assert.IsNotNull(statement); Assert.AreEqual("[Transaction]", statement.From.First().Name); Assert.AreEqual("Start > '23/05/2011 2:51:54 PM'", statement.Where.Value); }
public Expression <Action <long, long, TPayload, TKey> > Coalesce <TPayload, TResult, TKey>(Expression <Action <long, long, TResult, TKey> > action, bool canBePunctuation = false) { if (this.InputType != null && typeof(TPayload) != this.InputType) { throw new InvalidOperationException(); } if (this.OutputType != null && typeof(TResult) != this.OutputType) { throw new InvalidOperationException(); } int variableCount = 0; var syncParam = action.Parameters[0]; var otherParam = action.Parameters[1]; var keyParam = action.Parameters[3]; var parameter = action.Parameters[2]; var currentStatement = action.Body; for (int index = this.expressions.Count - 1; index >= 0; index--) { var profile = this.expressions[index]; switch (profile.category) { case ExpressionCategory.Select: { var oldParameter = parameter; parameter = Expression.Variable(profile.inputType, "var" + ++variableCount); var selectBody = profile.expression.Body; if (profile.hasStartEdge) { selectBody = ParameterSubstituter.Replace(profile.expression.Parameters[0], syncParam, selectBody); } if (profile.hasKey) { selectBody = ParameterSubstituter.Replace(profile.expression.Parameters[profile.expression.Parameters.Count - 2], keyParam, selectBody); } selectBody = ParameterSubstituter.Replace(profile.expression.Parameters.Last(), parameter, selectBody); currentStatement = Expression.Block( new[] { oldParameter }, Expression.Assign(oldParameter, selectBody), currentStatement); break; } case ExpressionCategory.SelectMany: { var oldParameter = parameter; var enumerableParameter = Expression.Variable(profile.expression.ReturnType, "var" + ++variableCount); var indexParameter = Expression.Variable(typeof(int), "var" + ++variableCount); parameter = Expression.Variable(profile.inputType, "var" + ++variableCount); var selectManyBody = profile.expression.Body; if (profile.hasStartEdge) { selectManyBody = ParameterSubstituter.Replace(profile.expression.Parameters[0], syncParam, selectManyBody); } if (profile.hasKey) { selectManyBody = ParameterSubstituter.Replace(profile.expression.Parameters[profile.expression.Parameters.Count - 2], keyParam, selectManyBody); } selectManyBody = ParameterSubstituter.Replace(profile.expression.Parameters.Last(), parameter, selectManyBody); var label = Expression.Label(); if (enumerableParameter.Type.IsArray) { currentStatement = Expression.Block( new[] { indexParameter, enumerableParameter }, Expression.Assign(indexParameter, Expression.Constant(0)), Expression.Assign(enumerableParameter, selectManyBody), Expression.Loop( Expression.Block( new[] { oldParameter }, Expression.IfThen( Expression.GreaterThanOrEqual(indexParameter, Expression.PropertyOrField(enumerableParameter, "Length")), Expression.Break(label)), Expression.Assign(oldParameter, Expression.ArrayIndex(enumerableParameter, indexParameter)), currentStatement, Expression.Increment(indexParameter)), label)); } else { var enumerableType = typeof(IEnumerable <>).GetTypeInfo().MakeGenericType(profile.outputType); var enumeratorType = typeof(IEnumerator <>).GetTypeInfo().MakeGenericType(profile.outputType); var enumeratorMethod = enumerableType.GetTypeInfo().GetMethod("GetEnumerator"); var enumeratorParameter = Expression.Variable(enumeratorType, enumerableParameter.Name + "Enumerator"); var moveNextMethod = typeof(IEnumerator).GetTypeInfo().GetMethod("MoveNext"); var disposeMethod = typeof(IDisposable).GetTypeInfo().GetMethod("Dispose"); currentStatement = Expression.Block( new[] { enumerableParameter, enumeratorParameter }, Expression.Assign(enumerableParameter, selectManyBody), Expression.Assign(enumeratorParameter, Expression.Call(enumerableParameter, enumeratorMethod)), Expression.Loop( Expression.Block( new[] { oldParameter }, Expression.IfThen( Expression.Not(Expression.Call(enumeratorParameter, moveNextMethod)), Expression.Break(label)), Expression.Assign(oldParameter, Expression.Property(enumeratorParameter, "Current")), currentStatement), label), Expression.Call(enumeratorParameter, disposeMethod)); } break; } case ExpressionCategory.Where: { currentStatement = Expression.IfThen( profile.expression.ReplaceParametersInBody(parameter), currentStatement); break; } default: throw new InvalidOperationException("Switch statement expected to be exhaustive."); } } if (this.durationAdjustment != null) { currentStatement = Expression.Block(Expression.IfThen( Expression.GreaterThan(otherParam, syncParam), Expression.Block( Expression.Assign( otherParam, this.durationAdjustment.ExpressionEquals(Expression.Constant(StreamEvent.InfinitySyncTime)) ? this.durationAdjustment : Expression.Add(syncParam, this.durationAdjustment)), currentStatement))); } if (canBePunctuation) { currentStatement = Expression.Block(Expression.IfThenElse( Expression.Equal(otherParam, Expression.Constant(long.MinValue)), ParameterSubstituter.Replace(action.Parameters[2], Expression.Constant(default(TResult), typeof(TResult)), action.Body), currentStatement)); } return(Expression.Lambda <Action <long, long, TPayload, TKey> >(currentStatement, syncParam, otherParam, parameter, keyParam)); }
public FuseModule FuseSelectManyWithKey <TKey, TPayload, TResult>(Expression <Func <long, TKey, TPayload, IEnumerable <TResult> > > selector) { if (this.expressions.Count == 0) { this.expressions.Add(new ExpressionProfile { category = ExpressionCategory.SelectMany, hasKey = true, hasStartEdge = true, keyType = typeof(TKey), inputType = typeof(TPayload), outputType = typeof(TResult), expression = selector }); return(this); } var prev = this.expressions[this.expressions.Count - 1]; switch (prev.category) { case ExpressionCategory.Select: { var body = ParameterSubstituter.Replace(selector.Parameters[2], prev.expression.Body, selector.Body); var payloadParameter = prev.expression.Parameters.Last().Yield(); IEnumerable <ParameterExpression> startEdgeParameter; if (prev.hasStartEdge) { var startEdge = prev.expression.Parameters[0]; body = ParameterSubstituter.Replace(selector.Parameters[0], startEdge, body); startEdgeParameter = startEdge.Yield(); } else { startEdgeParameter = selector.Parameters[0].Yield(); } IEnumerable <ParameterExpression> keyParameter; if (prev.hasKey) { var key = prev.expression.Parameters[prev.expression.Parameters.Count - 2]; body = ParameterSubstituter.Replace(selector.Parameters[1], key, body); keyParameter = key.Yield(); } else { keyParameter = selector.Parameters[1].Yield(); } prev.category = ExpressionCategory.SelectMany; prev.outputType = typeof(TResult); prev.hasKey = true; prev.keyType = typeof(TKey); prev.expression = Expression.Lambda(body, startEdgeParameter.Concat(keyParameter).Concat(payloadParameter)); break; } default: { this.expressions.Add(new ExpressionProfile { category = ExpressionCategory.SelectMany, hasKey = true, hasStartEdge = true, keyType = typeof(TKey), inputType = typeof(TPayload), outputType = typeof(TResult), expression = selector }); break; } } return(this); }