コード例 #1
0
        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;
                    }
                }
            }
        }
コード例 #2
0
 internal void Initialize(ODataNode node)
 {
     node.Uri = this;
     foreach (var child in node.Children)
     {
         Initialize(child);
     }
 }
コード例 #3
0
        public override int CompareTo(ODataNode other)
        {
            if (other is FilterNode)
            {
                return(0);
            }

            return(-1);
        }
コード例 #4
0
ファイル: SelectNode.cs プロジェクト: erdomke/ODataToolkit
        public override int CompareTo(ODataNode other)
        {
            if (other is SelectNode)
            {
                return(0);
            }

            return(1);
        }
コード例 #5
0
ファイル: OData.cs プロジェクト: erdomke/ODataToolkit
        /// <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());
        }
コード例 #6
0
ファイル: OData.cs プロジェクト: erdomke/ODataToolkit
 /// <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.");
 }
コード例 #7
0
        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));
            }
        }
コード例 #8
0
ファイル: SkipNode.cs プロジェクト: erdomke/ODataToolkit
        public override int CompareTo(ODataNode other)
        {
            if (other is SkipNode)
            {
                return(0);
            }

            if (other is OrderByNode || other is FilterNode)
            {
                return(1);
            }

            return(-1);
        }
コード例 #9
0
 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);
         }
     }
 }
コード例 #10
0
        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)));
        }
コード例 #11
0
        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);
        }
コード例 #12
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));
            }
        }
コード例 #13
0
        /// <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
            });
        }
コード例 #14
0
 internal void AddSegment(ODataNode node)
 {
     _segments.Add(node);
 }
コード例 #15
0
 public AscNode(ODataNode node) : base(new Token(TokenType.Identifier, "asc"))
 {
     Children.Add(node);
 }