Exemple #1
0
        public static Expression Bind(FilterQueryNode filterNode, Type filterType, IEdmModel model, bool handleNullPropagation)
        {
            if (filterNode == null)
            {
                throw Error.ArgumentNull("filterNode");
            }

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

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

            FilterBinder binder = new FilterBinder(model, handleNullPropagation);
            Expression   filter = binder.BindFilterQueryNode(filterNode);

            Type expectedFilterType = typeof(Func <,>).MakeGenericType(filterType, typeof(bool));

            if (filter.Type != expectedFilterType)
            {
                throw Error.InvalidOperation(SRResources.CannotCastFilter, filter.Type.FullName, expectedFilterType.FullName);
            }

            return(filter);
        }
        public static Expression Bind(FilterQueryNode filterNode, Type filterType, IEdmModel model, IAssembliesResolver assembliesResolver, ODataQuerySettings querySettings)
        {
            if (filterNode == null)
            {
                throw Error.ArgumentNull("filterNode");
            }

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

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

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

            FilterBinder binder = new FilterBinder(model, assembliesResolver, querySettings);
            Expression   filter = binder.BindFilterQueryNode(filterNode);

            Type expectedFilterType = typeof(Func <,>).MakeGenericType(filterType, typeof(bool));

            if (filter.Type != expectedFilterType)
            {
                throw Error.InvalidOperation(SRResources.CannotCastFilter, filter.Type.FullName, expectedFilterType.FullName);
            }

            return(filter);
        }
        private Expression BindFilterQueryNode(FilterQueryNode filterNode)
        {
            Type filterType = EdmLibHelpers.GetClrType(filterNode.ItemType, _model, _assembliesResolver);
            ParameterExpression filterParameter = Expression.Parameter(filterType, filterNode.Parameter.Name);

            _lambdaParameters = new Dictionary <string, ParameterExpression>();
            _lambdaParameters.Add(filterNode.Parameter.Name, filterParameter);

            Expression body = Bind(filterNode.Expression);

            body = ApplyNullPropagationForFilterBody(body);

            Expression filterExpression = Expression.Lambda(body, filterParameter);

            if (_parametersStack.Count != 0)
            {
                _lambdaParameters = _parametersStack.Pop();
            }
            else
            {
                _lambdaParameters = null;
            }

            return(filterExpression);
        }
Exemple #4
0
        /// <summary>
        /// Apply the filter query to the given IQueryable.
        /// </summary>
        /// <remarks>
        /// The <see cref="ODataQuerySettings.HandleNullPropagation"/> property specifies
        /// how this method should handle null propagation.
        /// </remarks>
        /// <param name="query">The IQueryable that we are applying filter query against.</param>
        /// <param name="querySettings">Specifies if we need to handle null propagation. Pass false if the underlying query provider handles null propagation. Otherwise pass true.</param>
        /// <param name="assembliesResolver">The <see cref="IAssembliesResolver"/> to use.</param>
        /// <returns>The query that the filter query has been applied to.</returns>
        public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings, IAssembliesResolver assembliesResolver)
        {
            if (query == null)
            {
                throw Error.ArgumentNull("query");
            }

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

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

            FilterQueryNode node = QueryNode;

            Contract.Assert(node != null);

            Expression filter = FilterBinder.Bind(node, Context.EntityClrType, Context.Model, assembliesResolver, querySettings);

            query = ExpressionHelpers.Where(query, filter, Context.EntityClrType);
            return(query);
        }
        /// <summary>
        /// Apply the filter query to the given IQueryable.
        /// </summary>
        /// <param name="query">The IQueryable that we are applying filter query against.</param>
        /// <param name="handleNullPropagation">Specifies if we need to handle null propagation. Pass false if the underlying query provider handles null propagation. Otherwise pass true.</param>
        /// <returns>The query that the filter query has been applied to.</returns>
        public IQueryable ApplyTo(IQueryable query, bool handleNullPropagation)
        {
            FilterQueryNode node = QueryNode;

            Contract.Assert(node != null);

            Expression filter = FilterBinder.Bind(node, Context.EntityClrType, Context.Model, handleNullPropagation);

            query = ExpressionHelpers.Where(query, filter, Context.EntityClrType);
            return(query);
        }
        /// <summary>
        /// Processes the filter of the query (if any).
        /// </summary>
        /// <param name="query">The query tree constructed so far.</param>
        /// <param name="filter">The filter to bind.</param>
        /// <returns>If no filter is specified, returns the <paramref name="query"/> unchanged. If a filter is specified it returns the combined query including the filter.</returns>
        private QueryNode ProcessFilter(QueryNode query, QueryToken filter)
        {
            ExceptionUtils.CheckArgumentNotNull(query, "query");

            if (filter != null)
            {
                CollectionQueryNode entityCollection = query.AsEntityCollectionNode();
                if (entityCollection == null)
                {
                    throw new ODataException(Strings.MetadataBinder_FilterNotApplicable);
                }

                this.parameter = new ParameterQueryNode() { ParameterType = entityCollection.ItemType };

                QueryNode expressionNode = this.Bind(filter);

                SingleValueQueryNode expressionResultNode = expressionNode as SingleValueQueryNode;
                if (expressionResultNode == null ||
                    (expressionResultNode.TypeReference != null && !expressionResultNode.TypeReference.IsODataPrimitiveTypeKind()))
                {
                    throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue);
                }

                // The type may be null here if the query statically represents the null literal
                // TODO: once we support open types/properties a 'null' type will mean 'we don't know the type'. Review.
                IEdmTypeReference expressionResultType = expressionResultNode.TypeReference;
                if (expressionResultType != null)
                {
                    IEdmPrimitiveTypeReference primitiveExpressionResultType = expressionResultType.AsPrimitiveOrNull();
                    if (primitiveExpressionResultType == null || primitiveExpressionResultType.PrimitiveKind() != EdmPrimitiveTypeKind.Boolean)
                    {
                        throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue);
                    }
                }

                query = new FilterQueryNode()
                {
                    Collection = entityCollection,
                    Parameter = this.parameter,
                    Expression = expressionResultNode
                };

                this.parameter = null;
            }

            return query;
        }
 public static Expression <Func <TEntityType, bool> > Bind <TEntityType>(FilterQueryNode filterNode, IEdmModel model, IAssembliesResolver assembliesResolver, ODataQuerySettings querySettings)
 {
     return(Bind(filterNode, typeof(TEntityType), model, assembliesResolver, querySettings) as Expression <Func <TEntityType, bool> >);
 }
        /// <summary>
        /// Translates a filter node.
        /// </summary>
        /// <param name="filterNode">The filter node to translate.</param>
        /// <returns>Expression which evaluates to the result after the filter operation.</returns>
        protected virtual Expression TranslateFilter(FilterQueryNode filterNode)
        {
            ExceptionUtils.CheckArgumentNotNull(filterNode, "filterNode");
            ExceptionUtils.CheckArgumentNotNull(filterNode.ItemType, "filterNode.ItemType");
            ExceptionUtils.CheckArgumentNotNull(filterNode.Collection, "filterNode.Collection");
            ExceptionUtils.CheckArgumentNotNull(filterNode.Collection.ItemType, "filterNode.Collection.ItemType");
            ExceptionUtils.CheckArgumentNotNull(filterNode.Expression, "filterNode.Expression");
            ExceptionUtils.CheckArgumentNotNull(filterNode.Parameter, "filterNode.Parameter");
            ExceptionUtils.CheckArgumentNotNull(filterNode.Parameter.TypeReference, "filterNode.Parameter.Type");

            ParameterExpression parameter = Expression.Parameter(filterNode.Parameter.TypeReference.GetInstanceType(this.model), "it");
            Expression collectionExpression = this.Translate(filterNode.Collection);
            
            // TODO: If we should support Filter on IEnumerable, then we need to add support here
            Type expectedCollectionType = typeof(IQueryable<>).MakeGenericType(parameter.Type);
            if (!expectedCollectionType.IsAssignableFrom(collectionExpression.Type))
            {
                throw new ODataException(Strings.QueryExpressionTranslator_FilterCollectionOfWrongType(collectionExpression.Type, expectedCollectionType));
            }

            this.parameterNodeDefinitions.Push(new KeyValuePair<ParameterQueryNode, Expression>(filterNode.Parameter, parameter));
            Expression body = this.Translate(filterNode.Expression);
            Debug.Assert(this.parameterNodeDefinitions.Peek().Key == filterNode.Parameter, "The parameter definition stack was not balanced correctly.");
            Debug.Assert(this.parameterNodeDefinitions.Peek().Value == parameter, "The parameter definition stack was not balanced correctly.");
            this.parameterNodeDefinitions.Pop();

            // TODO: Deal with open expressions
            if (body == nullLiteralExpression)
            {
                // lifting rules say that a null literal is interpreted as 'false' when treated as boolean.
                body = falseLiteralExpression;
            }
            else if (body.Type == typeof(bool?))
            {
                Expression test = Expression.Equal(body, Expression.Constant(null, typeof(bool?)));
                body = Expression.Condition(test, falseLiteralExpression, Expression.Property(body, "Value"));
            }

            if (body.Type != typeof(bool))
            {
                throw new ODataException(Strings.QueryExpressionTranslator_FilterExpressionOfWrongType(body.Type));
            }

            return Expression.Call(
                typeof(Queryable),
                WhereMethodName,
                new Type[] { parameter.Type },
                collectionExpression,
                Expression.Quote(Expression.Lambda(body, parameter)));
        }
 private void ProcessFilter(FilterQueryNode filterQuery)
 {
     var filterSparqlExpression = ProcessNode(filterQuery.Expression);
     _sparqlModel.CurrentGraphPattern.AddFilterExpression(filterSparqlExpression.ToString());
 }
        /// <summary>
        /// Processes the filter of the query (if any).
        /// </summary>
        /// <param name="query">The query tree constructed so far.</param>
        /// <param name="filter">The filter to bind.</param>
        /// <returns>If no filter is specified, returns the <paramref name="query"/> unchanged. If a filter is specified it returns the combined query including the filter.</returns>
        private QueryNode ProcessFilter(QueryNode query, QueryToken filter)
        {
            ExceptionUtils.CheckArgumentNotNull(query, "query");

            if (filter != null)
            {
                CollectionQueryNode entityCollection = query.AsEntityCollectionNode();
                if (entityCollection == null)
                {
                    throw new ODataException(Strings.MetadataBinder_FilterNotApplicable);
                }

                this.parameter = new ParameterQueryNode() { ParameterResourceType = entityCollection.ItemType };

                QueryNode expressionNode = this.Bind(filter);

                SingleValueQueryNode expressionResultNode = expressionNode as SingleValueQueryNode;
                if (expressionResultNode == null ||
                    (expressionResultNode.ResourceType != null && expressionResultNode.ResourceType.ResourceTypeKind != ResourceTypeKind.Primitive))
                {
                    throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue);
                }

                // The resource type may be null here if the query statically represents the null literal
                // TODO: once we support open types/properties a 'null' resource type will mean 'we don't know the type'. Review.
                if (expressionResultNode.ResourceType != null &&
                    !this.ResourceTypesEqual(expressionResultNode.ResourceType, PrimitiveTypeUtils.BoolResourceType) &&
                    !this.ResourceTypesEqual(expressionResultNode.ResourceType, PrimitiveTypeUtils.NullableBoolResourceType))
                {
                    throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue);
                }

                query = new FilterQueryNode()
                {
                    Collection = entityCollection,
                    Parameter = this.parameter,
                    Expression = expressionResultNode
                };

                this.parameter = null;
            }

            return query;
        }
Exemple #11
0
 public static Expression <Func <TEntityType, bool> > Bind <TEntityType>(FilterQueryNode filterNode, IEdmModel model, bool handleNullPropagation)
 {
     return(Bind(filterNode, typeof(TEntityType), model, handleNullPropagation) as Expression <Func <TEntityType, bool> >);
 }
Exemple #12
0
        private void ProcessFilter(FilterQueryNode filterQuery)
        {
            var filterSparqlExpression = ProcessNode(filterQuery.Expression);

            _sparqlModel.CurrentGraphPattern.AddFilterExpression(filterSparqlExpression.ToString());
        }