예제 #1
0
        private static Expression GetThenByCall(this Expression expression, OrderByClause orderByClause)
        {
            const string ThenBy           = "ThenBy";
            const string ThenByDescending = "ThenByDescending";

            return(orderByClause.ThenBy == null
                ? GetMethodCall()
                : GetMethodCall().GetThenByCall(orderByClause.ThenBy));

            Expression GetMethodCall()
            {
                return(orderByClause.Expression switch
                {
                    CountNode countNode => expression.GetOrderByCountCall
                    (
                        countNode.GetPropertyPath(),
                        orderByClause.Direction == OrderByDirection.Ascending
                            ? ThenBy
                            : ThenByDescending
                    ),
                    SingleValuePropertyAccessNode propertyNode => expression.GetOrderByCall
                    (
                        propertyNode.GetPropertyPath(),
                        orderByClause.Direction == OrderByDirection.Ascending
                            ? ThenBy
                            : ThenByDescending
                    ),
                    _ => throw new ArgumentException($"Unsupported SingleValueNode value: {orderByClause.Expression.GetType()}"),
                });
            }
예제 #2
0
        /// <summary>
        /// Translates a <see cref="CountNode"/> into a corresponding <see cref="String"/>.
        /// </summary>
        /// <param name="node">The node to translate.</param>
        /// <returns>The translated String.</returns>
        public override String Visit(CountNode node)
        {
            ExceptionUtils.CheckArgumentNotNull(node, "node");

            String source = this.TranslateNode(node.Source);
            return string.Concat(source, ExpressionConstants.SymbolForwardSlash, UriQueryConstants.CountSegment);
        }
        public override Expression Visit(CountNode nodeIn)
        {
            var navigation            = (CollectionNavigationNode)nodeIn.Source;
            MemberExpression property = Expression.Property(Parameter, navigation.NavigationProperty.Name);
            var typeArguments         = new Type[] { OeExpressionHelper.GetCollectionItemType(property.Type) };

            return(Expression.Call(typeof(Enumerable), nameof(Enumerable.Count), typeArguments, property));
        }
        /// <summary>
        /// Translate a CountNode.
        /// </summary>
        /// <param name="nodeIn">The node to be translated.</param>
        /// <returns>The translated node.</returns>
        public override QueryNode Visit(CountNode nodeIn)
        {
            if (nodeIn == null)
            {
                throw Error.ArgumentNull(nameof(nodeIn));
            }

            return(new CountNode((CollectionNode)nodeIn.Source.Accept(this)));
        }
예제 #5
0
        public override QueryNode Visit(CountNode nodeIn)
        {
            CollectionNode?source = nodeIn.Source == null ? null : (CollectionNode)Visit(nodeIn.Source);

            if (nodeIn.Source != source)
            {
                nodeIn = new CountNode(source);
            }
            return(nodeIn);
        }
        protected virtual QueryNode VisitCount(CountNode node, AzureQueryOptimizerState state)
        {
            QueryNode queryNode1 = this.Visit(node.SourceNode, state);
            QueryNode queryNode2 = this.Visit(node.PredicateNode, state);

            if (queryNode2.NodeType == QueryNodeType.MatchAll)
            {
                return((QueryNode) new CountNode(queryNode1, queryNode2, node.IsLongCount));
            }
            return((QueryNode) new CountNode(this.VisitAnd(new AndNode(queryNode1, queryNode2), state), (QueryNode) new MatchAllNode(), node.IsLongCount));
        }
        protected virtual QueryNode VisitCount(CountNode node, ElasticSearchQueryOptimizerState state)
        {
            QueryNode node2 = Visit(node.SourceNode, state);
            QueryNode node3 = Visit(node.PredicateNode, state);

            if (node3.NodeType == QueryNodeType.MatchAll)
            {
                return(new CountNode(node2, node3, node.IsLongCount));
            }
            return(new CountNode(VisitAnd(new AndNode(node2, node3), state), new MatchAllNode(), node.IsLongCount));
        }
예제 #8
0
        /// <summary>
        /// Writes CountNode.
        /// </summary>
        /// <param name="node">Node to write to string</param>
        /// <returns>String representation of node.</returns>
        private static string ToString(CountNode node)
        {
            if (node != null)
            {
                return(tabHelper.Prefix + "CountNode" +
                       tabHelper.Indent(() =>
                                        tabHelper.Prefix + "Source = " + ToString(node.Source)
                                        ));
            }

            return(String.Empty);
        }
        /// <summary>
        /// Visit a CountNode
        /// </summary>
        /// <param name="nodeIn">The node to visit</param>
        /// <returns>The translated expression</returns>
        public override Expression Visit(CountNode nodeIn)
        {
            this.CheckArgumentNull(nodeIn, "CountNode");

            Type       propType = null;
            Expression propExpr = null;

            // Element of collection could be primitive type or enum or complex or entity type
            if (nodeIn.Source.ItemType.IsPrimitive() || nodeIn.Source.ItemType.IsEnum())
            {
                var collection = (CollectionPropertyAccessNode)nodeIn.Source;
                propExpr = Visit(collection);
                var def = collection.Property.Type.AsCollection();
                propType = EdmClrTypeUtils.GetInstanceType(def.ElementType());
            }
            else if ((nodeIn.Source.ItemType.IsComplex() && nodeIn.Source.Kind.Equals(QueryNodeKind.CollectionComplexNode)))
            {
                // This does not handle complex collection cast case, if it is a complex collection cast, the Kind will be CollectionComplexCast and node.Source is CollectionComplexCastNode
                var collection = (CollectionComplexNode)nodeIn.Source;
                propExpr = Visit(collection);
                var def = collection.Property.Type.AsCollection();
                propType = EdmClrTypeUtils.GetInstanceType(def.ElementType());
            }
            else if (nodeIn.Source.ItemType.IsEntity() &&
                     nodeIn.Source.Kind.Equals(QueryNodeKind.CollectionNavigationNode))
            {
                // This does not handle entity collection cast case, if it is a entity collection cast, the Kind will be CollectionResourceCast and node.Source is CollectionResourceCastNode
                var collection = (CollectionNavigationNode)nodeIn.Source;
                propExpr = Visit(collection);
                var def = collection.NavigationProperty.Type.AsCollection();
                propType = EdmClrTypeUtils.GetInstanceType(def.ElementType());
            }
            else
            {
                // Should no such case as collection item is either primitive or enum or complex or entity.
                throw new NotSupportedException(
                          string.Format(
                              "Filter based on count of collection with item of type {0} is not supported yet.",
                              nodeIn.Source.ItemType));
            }

            // Per standard, collection can not be null, but could be an empty collection, so null is not considered here.
            var        asQuerableMethod     = _queryableAsQueryableMethod.MakeGenericMethod(propType);
            Expression asQuerableExpression = Expression.Call(null, asQuerableMethod, propExpr);

            var countMethod     = _countMethod.MakeGenericMethod(propType);
            var countExpression = Expression.Call(null, countMethod, asQuerableExpression);

            return(countExpression);
        }
예제 #10
0
        /// <summary>
        /// Override this method to restrict the '$count' inside the filter query.
        /// </summary>
        /// <param name="countNode">The count node to validate.</param>
        /// <param name="settings">The validation settings.</param>
        protected virtual void ValidateCountNode(CountNode countNode, ODataValidationSettings settings)
        {
            Contract.Assert(countNode != null);
            Contract.Assert(settings != null);

            ValidateQueryNode(countNode.Source, settings);

            if (countNode.FilterClause != null)
            {
                ValidateQueryNode(countNode.FilterClause.Expression, settings);
            }

            if (countNode.SearchClause != null)
            {
                ValidateQueryNode(countNode.SearchClause.Expression, settings);
            }
        }
예제 #11
0
        /// <summary>
        /// Translates a <see cref="CountNode"/> into a corresponding <see cref="String"/>.
        /// </summary>
        /// <param name="node">The node to translate.</param>
        /// <returns>The translated String.</returns>
        public override String Visit(CountNode node)
        {
            ExceptionUtils.CheckArgumentNotNull(node, "node");

            String source = this.TranslateNode(node.Source);

            source = string.Concat(source, ExpressionConstants.SymbolForwardSlash, UriQueryConstants.CountSegment);
            if (node.FilterOption != null)
            {
                source = string.Concat(
                    source,
                    ExpressionConstants.SymbolOpenParen,
                    UriQueryConstants.FilterQueryOption,
                    ExpressionConstants.SymbolEqual,
                    this.TranslateNode(node.FilterOption.Expression),
                    ExpressionConstants.SymbolClosedParen);
            }
            return(source);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="OrderByPropertyNode"/> class.
        /// </summary>
        /// <param name="orderByClause">The orderby clause representing property access.</param>
        public OrderByCountNode(OrderByClause orderByClause)
            : base(orderByClause)
        {
            if (orderByClause == null)
            {
                throw Error.ArgumentNull("orderByClause");
            }

            OrderByClause = orderByClause;
            Direction     = orderByClause.Direction;

            CountNode propertyExpression = orderByClause.Expression as CountNode;

            if (propertyExpression == null)
            {
                throw new ODataException(SRResources.OrderByClauseNotSupported);
            }
            else
            {
                Property = (propertyExpression.Source as CollectionNavigationNode).NavigationProperty;
            }
        }
예제 #13
0
        private Expression BindCountNode(CountNode node)
        {
            Expression source          = Bind(node.Source);
            Expression countExpression = Expression.Constant(null, typeof(long?));
            Type       elementType;

            if (!TypeHelper.IsCollection(source.Type, out elementType))
            {
                return(countExpression);
            }

            MethodInfo countMethod;

            if (typeof(IQueryable).IsAssignableFrom(source.Type))
            {
                countMethod = ExpressionHelperMethods.QueryableCountGeneric.MakeGenericMethod(elementType);
            }
            else
            {
                countMethod = ExpressionHelperMethods.EnumerableCountGeneric.MakeGenericMethod(elementType);
            }

            // call Count() method.
            countExpression = Expression.Call(null, countMethod, new[] { source });

            if (QuerySettings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // source == null ? null : countExpression
                return(Expression.Condition(
                           test: Expression.Equal(source, Expression.Constant(null)),
                           ifTrue: Expression.Constant(null, typeof(long?)),
                           ifFalse: ExpressionHelpers.ToNullable(countExpression)));
            }
            else
            {
                return(countExpression);
            }
        }
예제 #14
0
        /// <summary>
        /// Override this method to restrict the '$count' inside the filter query.
        /// </summary>
        /// <param name="countNode"></param>
        /// <param name="settings"></param>
        public virtual void ValidateCountNode(CountNode countNode, ODataValidationSettings settings)
        {
            if (countNode == null)
            {
                throw Error.ArgumentNull("countNode");
            }

            if (settings == null)
            {
                throw Error.ArgumentNull("settings");
            }

            ValidateQueryNode(countNode.Source, settings);

            if (countNode.FilterClause != null)
            {
                ValidateQueryNode(countNode.FilterClause.Expression, settings);
            }

            if (countNode.SearchClause != null)
            {
                ValidateQueryNode(countNode.SearchClause.Expression, settings);
            }
        }
예제 #15
0
 public override QueryNode Visit(CountNode nodeIn)
 {
     nodeIn.Source.Accept(this);
     return(nodeIn);
 }
예제 #16
0
 /// <summary>
 /// Translate a CountNode.
 /// </summary>
 /// <param name="nodeIn">The node to be translated.</param>
 /// <returns>The translated node.</returns>
 public override QueryNode Visit(CountNode nodeIn)
 {
     return(new CountNode((CollectionNode)nodeIn.Source.Accept(this)));
 }
예제 #17
0
 /// <summary>
 /// Visit a CountNode
 /// </summary>
 /// <param name="nodeIn">the node to visit</param>
 /// <returns>Defined by the implementer</returns>
 public virtual T Visit(CountNode nodeIn)
 {
     throw new NotImplementedException();
 }
예제 #18
0
        /// <summary>
        /// Translate a CountNode.
        /// </summary>
        /// <param name="nodeIn">The node to be translated.</param>
        /// <returns>The translated node.</returns>
        public override QueryNode Visit(CountNode nodeIn)
        {
            Contract.Assert(nodeIn != null);

            return(new CountNode((CollectionNode)nodeIn.Source.Accept(this)));
        }
 private bool Visit(CountNode node1, CountNode node2)
 {
     return(node1.TypeReference.IsEqual(node2.TypeReference) && Compare(node1.Source, node2.Source));
 }
예제 #20
0
 /// <summary>
 /// Translate a CountNode.
 /// </summary>
 /// <param name="nodeIn">The node to be translated.</param>
 /// <returns>The translated node.</returns>
 public override QueryNode Visit(CountNode nodeIn)
 {
     return(new CountNode((CollectionNode)nodeIn.Source.Accept(this), nodeIn.FilterClause, nodeIn.SearchClause));
 }
 public override T Visit(CountNode nodeIn)
 {
     SkipDebuggerBreak(nodeIn); /* nodeIn.Source.Accept(this); */ return(Visited);
 }
예제 #22
0
        public override int Visit(CountNode nodeIn)
        {
            var sourceNode = (CollectionNavigationNode)nodeIn.Source;

            return(sourceNode.NavigationProperty.Name.GetHashCode());
        }
예제 #23
0
 public override object Visit(CountNode nodeIn)
 {
     return(null);
 }
예제 #24
0
        private Expression BindCountNode(CountNode node)
        {
            Expression source          = Bind(node.Source);
            Expression countExpression = Expression.Constant(null, typeof(long?));
            Type       elementType;

            if (!TypeHelper.IsCollection(source.Type, out elementType))
            {
                return(countExpression);
            }

            MethodInfo countMethod;

            if (typeof(IQueryable).IsAssignableFrom(source.Type))
            {
                countMethod = ExpressionHelperMethods.QueryableCountGeneric.MakeGenericMethod(elementType);
            }
            else
            {
                countMethod = ExpressionHelperMethods.EnumerableCountGeneric.MakeGenericMethod(elementType);
            }

            MethodInfo whereMethod;

            if (typeof(IQueryable).IsAssignableFrom(source.Type))
            {
                whereMethod = ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(elementType);
            }
            else
            {
                whereMethod = ExpressionHelperMethods.EnumerableWhereGeneric.MakeGenericMethod(elementType);
            }

            // Bind the inner $filter clause within the $count segment.
            // e.g Books?$filter=Authors/$count($filter=Id gt 1) gt 1
            Expression filterExpression = null;

            if (node.FilterClause != null)
            {
                filterExpression = BindFilterClause(this, node.FilterClause, elementType);

                // The source expression looks like: $it.Authors
                // So the generated source expression below will look like: $it.Authors.Where($it => $it.Id > 1)
                source = Expression.Call(null, whereMethod, new[] { source, filterExpression });
            }

            // append LongCount() method.
            // The final countExpression with the nested $filter clause will look like: $it.Authors.Where($it => $it.Id > 1).LongCount()
            // The final countExpression without the nested $filter clause will look like: $it.Authors.LongCount()
            countExpression = Expression.Call(null, countMethod, new[] { source });

            if (QuerySettings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // source == null ? null : countExpression
                return(Expression.Condition(
                           test: Expression.Equal(source, Expression.Constant(null)),
                           ifTrue: Expression.Constant(null, typeof(long?)),
                           ifFalse: ExpressionHelpers.ToNullable(countExpression)));
            }
            else
            {
                return(countExpression);
            }
        }
예제 #25
0
 /// <summary>
 /// Visit a CountNode
 /// </summary>
 /// <param name="nodeIn">the node to visit</param>
 /// <returns>true, indicating that the node has been visited.</returns>
 public override bool Visit(CountNode nodeIn)
 {
     validate(nodeIn);
     return(true);
 }
 protected virtual void StripCount(CountNode node, HashSet <QueryMethod> additionalQueryMethods)
 {
     additionalQueryMethods.Add(new CountMethod(node.IsLongCount));
 }