private static void HandleSetOperation(Select select, MethodCallExpression expression, bool intersect, Func <IQueryable <T>, string> getTableName) { if (select.SetOperatons == null) { select.SetOperatons = new List <SetOperation>(); } var setOperationSource = CreateModel(expression.ArgumentAt(2), getTableName).Select; setOperationSource.Top = 1; setOperationSource.TopType = Select.TopValueType.Count; var operatorExpressions = expression.ArgumentAt <NewArrayExpression>(3). Expressions. Select(x => x.NodeType == ExpressionType.Quote ? ((UnaryExpression)x).Operand : x). Select(x => ((LambdaExpression)x).Body). Select(x => x.NodeType == ExpressionType.Convert ? ((UnaryExpression)x).Operand : x); var operators = operatorExpressions.Select(x => Operator.Create.Equal(Operand.Create.Projection(ProjectionVisitor <T> .CreateModel(x)), Operand.Create.Projection(ProjectionVisitor <T> .CreateModel(x, select.From.Alias)))); foreach (var @operator in operators) { setOperationSource.Where = setOperationSource.HasWhere ? Operator.Create.Operators(setOperationSource.Where, Operator.OperatorType.And, @operator) : @operator; } setOperationSource.Projection = operatorExpressions.Select(x => SelectProjection.Create(ProjectionVisitor <T> .CreateModel(x))).ToList(); select.SetOperatons.Add(new SetOperation { Type = intersect ? SetOperation.OperationType.Intersect : SetOperation.OperationType.Compliment, Select = setOperationSource }); }
private static void HandleDuplicates(Select select, MethodCallExpression expression) { if (select.Duplicates == null) { select.Duplicates = new Duplicates(); } select.Duplicates.Distinct = ProjectionVisitor <T> .CreateModel(expression.ArgumentAt(2)); if (expression.Arguments.Count == 2) { select.Duplicates.OrderBy.Add(new OrderBy { Type = OrderBy.SourceType.Projection, Projection = select.Duplicates.Distinct, Order = Order.Ascending }); } else { Enumerable.Range(3, expression.Arguments.Count - 2) .Where(x => x % 2 == 1) .Select(x => new { Index = x, IsProjection = ProjectionVisitor <T> .IsProjection(expression.ArgumentAt(x).GetLambdaBody()) }) .ToList().ForEach(x => select.Duplicates.OrderBy.Add(new OrderBy { Type = x.IsProjection ? OrderBy.SourceType.Projection : OrderBy.SourceType.Operator, Projection = x.IsProjection ? ProjectionVisitor <T> .CreateModel(expression.ArgumentAt(x.Index)) : null, Operator = !x.IsProjection ? WhereVisitor <T> .CreateModel(expression.ArgumentAt(x.Index), select.From.Alias) : null, Order = expression.ConstantArgumentAt <Order>(x.Index + 1) })); } }
private static void HandleDistinct(Select select, MethodCallExpression expression) { if (select.Distinct == null) { select.Distinct = new List <Distinct>(); } select.Distinct.Insert(0, new Distinct { Projection = ProjectionVisitor <T> .CreateModel(expression.ArgumentAt(2)), Order = expression.HasArguments(4) ? new OrderBy { Type = OrderBy.SourceType.Projection, Projection = ProjectionVisitor <T> .CreateModel(expression.ArgumentAt(3)), Order = expression.ConstantArgumentAt <Order>(4) } : null }); }
private static void HandleOrderBy(Select select, MethodCallExpression expression, bool descending) { if (select.OrderBy == null) { select.OrderBy = new List <OrderBy>(); } select.OrderBy.Insert(0, new OrderBy { Order = descending ? Order.Descending : Order.Ascending, Projection = ProjectionVisitor <T> .CreateModel(expression.ArgumentAt(2)), Type = OrderBy.SourceType.Projection }); }
private void HandleSync(Query target, MethodCallExpression expression) { target.Operation = Query.OperationType.SyncWith; var fields = expression.ArgumentAt <NewArrayExpression>(5).Expressions.Select(x => x.GetLambdaBody().StripConversion()); var exclude = expression.ConstantArgumentAt <SyncFields>(4) == SyncFields.Exclude; var source = CreateModel(expression.ArgumentAt(2), _getTableName).Select; if (!exclude) { source.Projection = fields.Select(x => new SelectProjection { Projection = ProjectionVisitor <T> .CreateModel(x, source.From.Alias) }).ToList(); target.Select.Projection = fields.Select(x => new SelectProjection { Projection = ProjectionVisitor <T> .CreateModel(x, target.Select.From.Alias) }).ToList(); } target.SyncWith = new Sync { Target = target.Select, Source = source, SourceKey = ProjectionVisitor <T> .CreateModel(expression.ArgumentAt(3), source.From.Alias), TargetKey = ProjectionVisitor <T> .CreateModel(expression.ArgumentAt(3), target.Select.From.Alias), ExcludedFields = exclude ? fields.Select(x => ProjectionVisitor <T> .CreateModel(x).Field).ToList() : new List <Field>() }; }
private static void HandleWhere(Select select, MethodCallExpression expression) { var where = WhereVisitor <T> .CreateModel(expression.ArgumentAt(2), select.From.Alias); if (!select.HasWhere) { select.Where = where; } else { var @operator = Operator.Create.ByType(Operator.OperatorType.And); @operator.LeftOperand = Operand.Create.Operator(select.Where); @operator.RightOperand = Operand.Create.Operator(where); select.Where = @operator; } }
protected override void VisitMethodCall(Context context, MethodCallExpression node) { var query = context.State; if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Union(Enumerable.Empty <T>()))) { AddSourceQuery(query.Select, CreateModel(node.ArgumentAt(2), _getTableName).Select); } else if (query.Select.From.HasQueries) { // If we have unions we need to nest subsequent query operators otherwise they would apply to the // net result of the union. This is consistent with the behavior of linq to objects. AddSourceQuery(query.Select, CreateModel(node, _getTableName).Select); return; } else { if (node.MatchesMethodSignature <IQueryable <T> >(x => x.CopyTo(Queryable.Empty <T>()))) { HandleSelectInto(query, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Where(y => true))) { HandleWhere(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Distinct(y => y))) { HandleDistinct(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Distinct(y => y, y => y, Order.Ascending))) { HandleDistinct(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Duplicates(y => y))) { HandleDuplicates(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Duplicates(y => y, y => y, Order.Ascending))) { HandleDuplicates(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Duplicates(y => y, y => y, Order.Ascending, y => y, Order.Ascending))) { HandleDuplicates(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.OrderBy(y => y))) { HandleOrderBy(query.Select, node, false); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.OrderByDescending(y => y))) { HandleOrderBy(query.Select, node, true); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Take(0))) { query.Select.Top = node.ConstantArgumentAt <int>(2); query.Select.TopType = Select.TopValueType.Count; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.TakePercent(0))) { query.Select.Top = node.ConstantArgumentAt <int>(2); query.Select.TopType = Select.TopValueType.Percent; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Skip(0))) { query.Select.Start = node.ConstantArgumentAt <int>(2) + 1; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Single())) { query.Select.Single = true; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Single(y => true))) { query.Select.Single = true; HandleWhere(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.First())) { query.Select.First = true; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.First(y => true))) { query.Select.First = true; HandleWhere(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.FirstOrDefault())) { query.Select.FirstOrDefault = true; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.FirstOrDefault(y => true))) { query.Select.FirstOrDefault = true; HandleWhere(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Any())) { query.Select.Any = true; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Any(y => true))) { query.Select.Any = true; HandleWhere(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Count())) { query.Select.Count = true; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Count(y => true))) { query.Select.Count = true; HandleWhere(query.Select, node); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Randomize())) { query.Select.Randomize = true; } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Intersect( Queryable.Empty <T>(), new Expression <Func <T, object> >[] { }))) { HandleSetOperation(query.Select, node, true, _getTableName); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.Except( Queryable.Empty <T>(), new Expression <Func <T, object> >[] { }))) { HandleSetOperation(query.Select, node, false, _getTableName); } else if (node.MatchesMethodSignature <IQueryable <T> >(x => x.SyncWith(Queryable.Empty <T>(), y => y, SyncFields.Exclude, new Expression <Func <T, object> >[] { }))) { HandleSync(query, node); } else { throw new QueryOperatorNotSupportedException(node.Method); } } VisitMethodCall(node, query, query, true, true, node.Arguments.Skip(1).ToArray()); }
public static T ArgumentAt <T>(this MethodCallExpression method, int index) where T : Expression { return((T)method.ArgumentAt(index)); }
public static bool ArgumentIsOfType <T>(this MethodCallExpression method, int index) { return(TypesAreAssignable(method.ArgumentAt(index).Type, typeof(T))); }
protected override void VisitMethodCall(Context context, MethodCallExpression node) { if (node.MatchesMethodSignature <string>(x => x.StartsWith(string.Empty))) { var projection = Projection.Create.Function(Function.Create.StartsWith()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.StartsWith.Value = x } }; VisitMethodCall(node, x => projection.Function.StartsWith.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.Contains(string.Empty))) { var projection = Projection.Create.Function(Function.Create.Contains()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.Contains.Value = x } }; VisitMethodCall(node, x => projection.Function.Contains.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.EndsWith(string.Empty))) { var projection = Projection.Create.Function(Function.Create.EndsWith()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.EndsWith.Value = x } }; VisitMethodCall(node, x => projection.Function.EndsWith.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.ToLower())) { var projection = Projection.Create.Function(Function.Create.ToLower()); context.State(projection); VisitMethodCall(node, x => projection.Function.ToLower.Text = x, true); } else if (node.MatchesMethodSignature <string>(x => x.ToUpper())) { var projection = Projection.Create.Function(Function.Create.ToUpper()); context.State(projection); VisitMethodCall(node, x => projection.Function.ToUpper.Text = x, true); } else if (node.MatchesMethodSignature <string>(x => x.Trim())) { var projection = Projection.Create.Function(Function.Create.Trim()); context.State(projection); VisitMethodCall(node, x => projection.Function.Trim.Text = x, true); } else if (node.MatchesMethodSignature <string>(x => x.TrimEnd())) { var projection = Projection.Create.Function(Function.Create.TrimEnd()); context.State(projection); VisitMethodCall(node, x => projection.Function.TrimEnd.Text = x, true); } else if (node.MatchesMethodSignature <string>(x => x.TrimStart())) { var projection = Projection.Create.Function(Function.Create.TrimStart()); context.State(projection); VisitMethodCall(node, x => projection.Function.TrimStart.Text = x, true); } else if (node.MatchesMethodSignature <string>(x => x.ToString())) { var projection = Projection.Create.Function(Function.Create.ToString()); context.State(projection); VisitMethodCall(node, x => projection.Function.ToString.Value = x, true); } else if (node.MatchesMethodSignature <string>(x => x.Substring(0))) { var projection = Projection.Create.Function(Function.Create.Substring()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.Substring.Start = x } }; VisitMethodCall(node, x => projection.Function.Substring.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.Substring(0, 0))) { var projection = Projection.Create.Function(Function.Create.SubstringFixed()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.SubstringFixed.Start = x }, { node.ArgumentAt(2), x => projection.Function.SubstringFixed.Length = x } }; VisitMethodCall(node, x => projection.Function.SubstringFixed.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.Replace(string.Empty, string.Empty))) { var projection = Projection.Create.Function(Function.Create.Replace()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.Replace.SearchValue = x }, { node.ArgumentAt(2), x => projection.Function.Replace.ReplaceValue = x } }; VisitMethodCall(node, x => projection.Function.Replace.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.Insert(0, string.Empty))) { var projection = Projection.Create.Function(Function.Create.Insert()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.Insert.Start = x }, { node.ArgumentAt(2), x => projection.Function.Insert.Value = x } }; VisitMethodCall(node, x => projection.Function.Insert.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.IndexOf(string.Empty))) { var projection = Projection.Create.Function(Function.Create.IndexOf()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.IndexOf.Value = x } }; VisitMethodCall(node, x => projection.Function.IndexOf.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.IndexOf(string.Empty, 0))) { var projection = Projection.Create.Function(Function.Create.IndexOfAt()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.IndexOfAt.Value = x }, { node.ArgumentAt(2), x => projection.Function.IndexOfAt.Start = x } }; VisitMethodCall(node, x => projection.Function.IndexOfAt.Text = x, argumentsState, true, true); } else if (node.MatchesMethodSignature <string>(x => x.Hash(EntityExtensions.HashAlgorithim.Md5))) { var projection = Projection.Create.Function(Function.Create.Hash(node.ConstantArgumentAt <EntityExtensions.HashAlgorithim>(2) == EntityExtensions.HashAlgorithim.Md5 ? Function.HashParameters.HashType.Md5 : Function.HashParameters.HashType.Sha1)); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.Hash.Value = x } }; VisitMethodCall(node, argumentsState, true, node.ArgumentAt(2)); } else if (node.MatchesMethodSignature <byte[]>(x => x.ToHex())) { var projection = Projection.Create.Function(Function.Create.ToHex()); context.State(projection); var argumentsState = new Dictionary <Expression, Action <Projection> > { { node.ArgumentAt(1), x => projection.Function.ToHex.Value = x } }; VisitMethodCall(node, argumentsState, true); } else if (node.Object != null && node.Object.NodeType == ExpressionType.MemberAccess && node.Object.Type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary <,>)) && node.MatchesMethodName("get_Item")) { context.State(Projection.Create.Field(((MemberExpression)node.Object).Member.Name, node.Arguments[0].EvaluateExpression <string>(), _tableAlias)); } else { context.State(Projection.Create.Constant(node.EvaluateExpression())); } }