private void CollectSegments(ODataNode node) { if (node.Type == TokenType.PathSeparator) { foreach (var child in node.Children) { switch (child.Type) { case TokenType.Scheme: case TokenType.Authority: case TokenType.Port: case TokenType.Colon: break; case TokenType.PathSeparator: CollectSegments(child); break; default: _uri.AddSegment(child); break; } } } }
internal void Initialize(ODataNode node) { node.Uri = this; foreach (var child in node.Children) { Initialize(child); } }
public override int CompareTo(ODataNode other) { if (other is FilterNode) { return(0); } return(-1); }
public override int CompareTo(ODataNode other) { if (other is SelectNode) { return(0); } return(1); }
/// <summary> /// Return the primitive value of a literal node (or the literal value /// referenced by an alias node). /// </summary> public static object AsPrimitive(this ODataNode node) { if (node is PlaceholderNode) { return(null); } var literal = (LiteralNode)node.GetValueNode(); return(literal.ToPrimitive()); }
/// <summary> /// Return the single child of an ODataNode /// </summary> public static ODataNode Child(this ODataNode node) { if (node.Children.Count < 1) { return(PlaceholderNode.Instance); } if (node.Children.Count == 1) { return(node.Children[0]); } throw new InvalidOperationException("OData node contains more than one child."); }
private static void BuildQuery(ODataNode node, Type inputType, Expression <Func <object, string, object> > dynamicAccessor, ref IQueryable queryResult, ref IQueryable constrainedQuery) { var type = queryResult.Provider.GetType().Name; if (!(node is TopNode) && !(node is SkipNode)) { var opts = new ExpressionOptions() { Query = queryResult, InputType = inputType, Expression = queryResult.Expression, DynamicAccessor = dynamicAccessor }; var modifier = node as QueryModifier; if (modifier != null) { queryResult = modifier.ModifyQuery(opts); } else { queryResult = queryResult.Provider.CreateQuery( node.BuildLinqExpression(opts)); } } var queryModifier = node as QueryModifier; if (queryModifier != null) { var opts = new ExpressionOptions() { Query = constrainedQuery, InputType = inputType, Expression = constrainedQuery.Expression, DynamicAccessor = dynamicAccessor }; constrainedQuery = queryModifier.ModifyQuery(opts); } else { var opts = new ExpressionOptions() { Query = constrainedQuery, InputType = inputType, Expression = constrainedQuery.Expression, DynamicAccessor = dynamicAccessor }; constrainedQuery = constrainedQuery.Provider.CreateQuery( node.BuildLinqExpression(opts)); } }
public override int CompareTo(ODataNode other) { if (other is SkipNode) { return(0); } if (other is OrderByNode || other is FilterNode) { return(1); } return(-1); }
private void CollectQueryTerms(ODataNode node) { if (node.Type == TokenType.QueryName || node.Type == TokenType.Parameter) { _uri.QueryOption.Add(node); } else { foreach (var child in node.Children) { CollectQueryTerms(child); } } }
private static IQueryable ProjectQuery(IQueryable constrainedQuery, ODataNode node, Type inputType, Expression <Func <object, string, object> > dynamicAccessor) { // TODO: Find a solution to the following: // Currently the only way to perform the SELECT part of the query is to call ToList and then project onto a dictionary. Two main problems: // 1. Linq to Entities does not support projection onto list initialisers with more than one value // 2. We cannot build an anonymous type using expression trees as there is compiler magic that must happen. // There is a solution involving reflection.emit, but is it worth it? Not sure... //var result = GetEnumeratedQuery(constrainedQuery).AsQueryable(); var opts = new ExpressionOptions() { Query = constrainedQuery, InputType = inputType, Expression = constrainedQuery.Expression, DynamicAccessor = dynamicAccessor }; return (constrainedQuery.Provider.CreateQuery( node.BuildLinqExpression(opts))); }
private int GetPrecedence(ODataNode node) { // TODO: isof and cast if (node.Type == TokenType.Navigation || node.Type == TokenType.Period) { return(170); } else if (node.Type == TokenType.Has) { return(170); } else if (node.Type == TokenType.Negate || node.Type == TokenType.Not) { return(160); } else if (node.Type == TokenType.Multiply || node.Type == TokenType.Divide || node.Type == TokenType.Modulo) { return(150); } else if (node.Type == TokenType.Add || node.Type == TokenType.Subtract) { return(140); } else if (node.Type == TokenType.GreaterThan || node.Type == TokenType.LessThan || node.Type == TokenType.GreaterThanOrEqual || node.Type == TokenType.LessThanOrEqual) { return(130); } else if (node.Type == TokenType.Equal || node.Type == TokenType.NotEqual) { return(120); } else if (node.Type == TokenType.And) { return(110); } else if (node.Type == TokenType.Or) { return(100); } else if (node is AscNode || node is DescNode) { return(95); } else if (node.Type == TokenType.Comma || node.Type == TokenType.Colon) { return(90); } else if (node.Type == TokenType.QueryAssign) { return(80); } else if (node.Type == TokenType.Amperstand) { return(70); } else if (node.Type == TokenType.PathSeparator) { return(60); } else if (node.Type == TokenType.Question) { return(50); } return(0); }
private ODataNode FromToken(Token token, ODataNode queryNode) { switch (token.Type) { case TokenType.Parameter: return(new AliasNode(token)); case TokenType.Base64: case TokenType.Binary: case TokenType.Date: case TokenType.Decimal: case TokenType.Double: case TokenType.Duration: case TokenType.False: case TokenType.Guid: case TokenType.Integer: case TokenType.Long: case TokenType.NaN: case TokenType.NegInfinity: case TokenType.PosInfinity: case TokenType.Single: case TokenType.String: case TokenType.True: return(new LiteralNode(token)); case TokenType.Null: return(new NullNode(token)); case TokenType.Identifier: case TokenType.Navigation: if (queryNode is OrderByNode && token.Text == "asc") { return(new AscNode(token)); } if (queryNode is OrderByNode && token.Text == "desc") { return(new DescNode(token)); } if (token.Text == "$count") { return(new CountNode(token)); } return(new IdentifierNode(token)); case TokenType.And: case TokenType.Or: case TokenType.Equal: case TokenType.NotEqual: case TokenType.LessThan: case TokenType.LessThanOrEqual: case TokenType.GreaterThan: case TokenType.GreaterThanOrEqual: case TokenType.Add: case TokenType.Subtract: case TokenType.Multiply: case TokenType.Divide: case TokenType.Modulo: return(new BinaryNode(token)); case TokenType.Not: return(new NotNode(token)); case TokenType.QueryName: switch (token.Text) { case "$filter": return(new FilterNode(token)); case "$select": return(new SelectNode(token)); case "$orderby": return(new OrderByNode(token)); case "$skip": return(new SkipNode(token)); case "$top": return(new TopNode(token)); case "$expand": return(new ExpandNode(token)); default: return(new IgnoredNode(token)); } default: return(new IgnoredNode(token)); } }
/// <summary> /// Execute the query represented by an OData URI against an <c>IQueryable</c> data source /// </summary> /// <param name="query"><c>IQueryable</c> data source</param> /// <param name="inputType">Model data type</param> /// <param name="dynamicAccessor">Expression for accessing fields on dynamic model objects</param> public ODataQueryable <object> Execute(IQueryable query, ExecutionSettings settings = null) { if (query == null) { throw new ArgumentNullException("query", "Query cannot be null"); } settings = settings ?? ExecutionSettings.Empty; var queryResult = query; var constrainedQuery = query; var path = settings.GetEdmSource(this); var inputType = settings.GetInputType(query); var dynamicAccessor = settings.GetDynamicAccessor(); var lookupByKey = false; var children = this.QueryOption.Where(n => !(n is IgnoredNode) && !(n is AliasNode)).ToList(); // Try and do an ID lookup if applicable var segments = PathSegments.ToArray(); var functionNode = segments.FirstOrDefault() as CallNode; if (functionNode != null && segments.Length == 1) { var entity = ((IEdmCollectionType)path.Type).ElementType.ToStructuredType() as IEdmEntityType; if (entity != null && entity.Key().Count() == functionNode.Arguments.Count) { var keys = entity.Key().ToArray(); var root = default(ODataNode); for (var i = 0; i < keys.Length; i++) { var newNode = ODataNode.Equals(ODataNode.Identifier(keys[i].Name), functionNode.Arguments[i]); if (root == null) { root = newNode; } else { newNode = ODataNode.And(root, newNode); } } children.RemoveByFilter(n => n is FilterNode); children.Add(ODataNode.Filter(root)); lookupByKey = true; } } var maxPageSize = settings.GetMaxPageSize(); if (maxPageSize.HasValue && (!QueryOption.Top.HasValue || maxPageSize.Value < QueryOption.Top.Value)) { children.RemoveByFilter(n => n is TopNode); children.Add(ODataNode.Top(ODataNode.Literal(maxPageSize.Value))); } children.Sort(); // These should always come first foreach (var node in children.Where(o => !(o is SelectNode))) { BuildQuery(node, inputType, dynamicAccessor, ref queryResult, ref constrainedQuery); } var selectNode = children.FirstOrDefault(o => o is SelectNode); if (selectNode != null) { constrainedQuery = ProjectQuery(constrainedQuery, selectNode, inputType, dynamicAccessor); } return(new ODataQueryable <object>(constrainedQuery, this) { LookupByKey = lookupByKey }); }
internal void AddSegment(ODataNode node) { _segments.Add(node); }
public AscNode(ODataNode node) : base(new Token(TokenType.Identifier, "asc")) { Children.Add(node); }