public static IList<string> GetPaths(FilterQueryOption filterOption, string separator = ".") { var findAnyAll = new FindNavigationFilterOptions(); findAnyAll.Find(filterOption.FilterClause.Expression); return findAnyAll.GetPaths(separator); }
/// <summary> /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from /// the <see cref="ODataQueryContext"/>. /// </summary> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param> /// <param name="request">The incoming request message</param> public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request) { if (context == null) { throw Error.ArgumentNull("context"); } if (request == null) { throw Error.ArgumentNull("request"); } // remember the context Context = context; // Parse the query from request Uri RawValues = new ODataRawQueryOptions(); IEnumerable<KeyValuePair<string, string>> queryParameters = request.GetQueryNameValuePairs(); foreach (KeyValuePair<string, string> kvp in queryParameters) { switch (kvp.Key) { case "$filter": RawValues.Filter = kvp.Value; ThrowIfEmpty(kvp.Value, "$filter"); Filter = new FilterQueryOption(kvp.Value, context); break; case "$orderby": RawValues.OrderBy = kvp.Value; ThrowIfEmpty(kvp.Value, "$orderby"); OrderBy = new OrderByQueryOption(kvp.Value, context); break; case "$top": RawValues.Top = kvp.Value; ThrowIfEmpty(kvp.Value, "$top"); Top = new TopQueryOption(kvp.Value, context); break; case "$skip": RawValues.Skip = kvp.Value; ThrowIfEmpty(kvp.Value, "$skip"); Skip = new SkipQueryOption(kvp.Value, context); break; case "$select": RawValues.Select = kvp.Value; break; case "$inlinecount": RawValues.InlineCount = kvp.Value; break; case "$expand": RawValues.Expand = kvp.Value; break; case "$skiptoken": RawValues.SkipToken = kvp.Value; break; default: // we don't throw if we can't recognize the query break; } } }
public void CanConstructValidFilterQuery(string filterValue) { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filter = new FilterQueryOption(filterValue, context); Assert.Same(context, filter.Context); Assert.Equal(filterValue, filter.RawValue); }
public static WhereClause BindFilterQueryOption(FilterQueryOption filterQuery) { if (filterQuery != null) { NHibernateFilterBinder binder = new NHibernateFilterBinder(filterQuery.Context.Model); return new WhereClause { Clause = "where " + binder.BindFilter(filterQuery) + Environment.NewLine, PositionalParameters = binder._positionalParmeters.ToArray() }; } return _emptyWhereClause; }
public void GetQueryNodeParsesQuery() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filter = new FilterQueryOption("Name eq 'MSFT'", context); var node = filter.QueryNode; Assert.Equal(QueryNodeKind.BinaryOperator, node.Expression.Kind); var binaryNode = node.Expression as BinaryOperatorQueryNode; Assert.Equal(BinaryOperatorKind.Equal, binaryNode.OperatorKind); Assert.Equal(QueryNodeKind.Constant, binaryNode.Right.Kind); Assert.Equal("MSFT", ((ConstantQueryNode)binaryNode.Right).Value); Assert.Equal(QueryNodeKind.PropertyAccess, binaryNode.Left.Kind); var propertyAccessNode = binaryNode.Left as PropertyAccessQueryNode; Assert.Equal("Name", propertyAccessNode.Property.Name); }
public void GetQueryNodeParsesQuery() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filter = new FilterQueryOption("Name eq 'MSFT'", context); var node = filter.QueryNode; Assert.Equal(QueryNodeKind.BinaryOperator, node.Expression.Kind); var binaryNode = node.Expression as BinaryOperatorQueryNode; Assert.Equal(BinaryOperatorKind.Equal, binaryNode.OperatorKind); Assert.Equal(QueryNodeKind.Constant, binaryNode.Right.Kind); Assert.Equal("MSFT", ((ConstantQueryNode)binaryNode.Right).Value); Assert.Equal(QueryNodeKind.PropertyAccess, binaryNode.Left.Kind); var propertyAccessNode = binaryNode.Left as PropertyAccessQueryNode; Assert.Equal("Name", propertyAccessNode.Property.Name); }
public void ApplyToEnums_ThrowsNotSupported_ForStringFunctions(string filter, string exceptionMessage) { // Arrange var builder = new ODataConventionModelBuilder(); builder.EntitySet <EnumModel>("EnumModels"); var model = builder.GetEdmModel(); var context = new ODataQueryContext(model, typeof(EnumModel), "EnumModels"); var filterOption = new FilterQueryOption(filter, context); IEnumerable <EnumModel> enumModels = EnumModelTestData; // Act Assert.Throws <ODataException>( () => filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }), exceptionMessage ); }
public void ApplyToEnums_ReturnsCorrectQueryable(string filter, int[] enumModelIds) { // Arrange var model = GetEnumModel(); var context = new ODataQueryContext(model, typeof(EnumModel)); var filterOption = new FilterQueryOption(filter, context); IEnumerable <EnumModel> enumModels = EnumModelTestData; // Act IQueryable queryable = filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }); // Assert Assert.NotNull(queryable); IEnumerable <EnumModel> actualCustomers = Assert.IsAssignableFrom <IEnumerable <EnumModel> >(queryable); Assert.Equal( enumModelIds, actualCustomers.Select(enumModel => enumModel.Id)); }
public void TestFilterVisitor() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.EntitySet<Bar>("Bar"); ODataQueryContext context = new ODataQueryContext(builder.GetEdmModel(), typeof(Bar)); //ODataQueryOptions<Customer> query = new ODataQueryOptions<Customer>(context, new HttpRequestMessage(HttpMethod.Get, "http://server/?$top=10")); FilterQueryOption f = new FilterQueryOption("startswith(BarString,'b') eq true", context); var fo = new FindNavigationFilterOptions(); fo.Find(f.FilterClause.Expression); List<string> pathsString = fo.GetPaths(); CollectionAssert.AreEqual(pathsString, new string[0]); f = new FilterQueryOption("F/FooId eq 1", context); fo = new FindNavigationFilterOptions(); fo.Find(f.FilterClause.Expression); pathsString = fo.GetPaths(); CollectionAssert.AreEqual(pathsString, new[] { "F" }); f = new FilterQueryOption("(startswith(BarString,'b') eq true) and (not (Foos/any(x1: x1/B/BarId eq 1)))", context); fo = new FindNavigationFilterOptions(); fo.Find(f.FilterClause.Expression); pathsString = fo.GetPaths(); CollectionAssert.AreEqual(pathsString, new[] { "Foos.B" }); f = new FilterQueryOption("Foos/any(x1: x1/B/BarId eq 1)", context); fo = new FindNavigationFilterOptions(); fo.Find(f.FilterClause.Expression); pathsString = fo.GetPaths(); CollectionAssert.AreEqual(pathsString, new[] { "Foos.B" }); f = new FilterQueryOption("F/Bars/any(x1: x1/BarId eq 1)", context); fo = new FindNavigationFilterOptions(); fo.Find(f.FilterClause.Expression); pathsString = fo.GetPaths(); CollectionAssert.AreEqual(pathsString, new[] { "F.Bars" }); }
public void CanConstructValidAnyQueryOverComplexCollectionProperty() { var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filter = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context); var node = filter.QueryNode; var anyNode = node.Expression as AnyQueryNode; var aParameter = anyNode.Parameters.SingleOrDefault(p => p.Name == "a"); var aParameterType = aParameter.ParameterType.Definition as IEdmComplexType; Assert.NotNull(aParameter); // There's currently a bug here. For now, the test checks for the presence of the bug (as a reminder to fix // the test once the bug is fixed). // The following asserts show the behavior with the bug and should be removed once the bug is fixed. Assert.Null(aParameterType); Assert.Equal("a", aParameter.Name); // TODO: Enable once Uri Parser sets parameters of Any/All bound to CollectionProperty correctly // The following asserts show the behavior without the bug, and should be enabled once the bug is fixed. //Assert.NotNull(aParameterType); //Assert.Equal("Address", aParameter.Name); }
public void CanConstructValidAnyQueryOverComplexCollectionProperty() { var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filter = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context); var node = filter.QueryNode; var anyNode = node.Expression as AnyQueryNode; var aParameter = anyNode.Parameters.SingleOrDefault(p => p.Name == "a"); var aParameterType = aParameter.ParameterType.Definition as IEdmComplexType; Assert.NotNull(aParameter); Assert.NotNull(aParameterType); Assert.Equal("Address", aParameter.Name); }
/// <summary> /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from /// the <see cref="ODataQueryContext"/>. /// </summary> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information.</param> /// <param name="request">The incoming request message.</param> public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request) { if (context == null) { throw Error.ArgumentNull("context"); } if (request == null) { throw Error.ArgumentNull("request"); } if (request.GetConfiguration() != null) { _assembliesResolver = request.GetConfiguration().Services.GetAssembliesResolver(); } // fallback to the default assemblies resolver if none available. _assembliesResolver = _assembliesResolver ?? new DefaultAssembliesResolver(); // remember the context and request Context = context; Request = request; // Parse the query from request Uri RawValues = new ODataRawQueryOptions(); IEnumerable <KeyValuePair <string, string> > queryParameters = request.GetQueryNameValuePairs(); foreach (KeyValuePair <string, string> kvp in queryParameters) { switch (kvp.Key) { case "$filter": RawValues.Filter = kvp.Value; ThrowIfEmpty(kvp.Value, "$filter"); Filter = new FilterQueryOption(kvp.Value, context); break; case "$orderby": RawValues.OrderBy = kvp.Value; ThrowIfEmpty(kvp.Value, "$orderby"); OrderBy = new OrderByQueryOption(kvp.Value, context); break; case "$top": RawValues.Top = kvp.Value; ThrowIfEmpty(kvp.Value, "$top"); Top = new TopQueryOption(kvp.Value, context); break; case "$skip": RawValues.Skip = kvp.Value; ThrowIfEmpty(kvp.Value, "$skip"); Skip = new SkipQueryOption(kvp.Value, context); break; case "$select": RawValues.Select = kvp.Value; break; case "$inlinecount": RawValues.InlineCount = kvp.Value; ThrowIfEmpty(kvp.Value, "$inlinecount"); InlineCount = new InlineCountQueryOption(kvp.Value, context); break; case "$expand": RawValues.Expand = kvp.Value; break; case "$format": RawValues.Format = kvp.Value; break; case "$skiptoken": RawValues.SkipToken = kvp.Value; break; default: // we don't throw if we can't recognize the query break; } } Validator = new ODataQueryValidator(); }
private static WhereClause ToFilterQuery(FilterQueryOption filterQuery) { return NHibernateFilterBinder.BindFilterQueryOption(filterQuery); }
public void ApplyTo_WithUnTypedContext_Throws_InvalidOperation() { CustomersModelWithInheritance model = new CustomersModelWithInheritance(); ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer); FilterQueryOption filter = new FilterQueryOption("Id eq 42", context); IQueryable queryable = new Mock<IQueryable>().Object; Assert.Throws<NotSupportedException>(() => filter.ApplyTo(queryable, new ODataQuerySettings()), "The query option is not bound to any CLR type. 'ApplyTo' is only supported with a query option bound to a CLR type."); }
public void Property_FilterClause_WorksWithUnTypedContext() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer); FilterQueryOption filter = new FilterQueryOption("ID eq 42", context); // Act & Assert Assert.NotNull(filter.FilterClause); }
public override void Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings) { base.Validate(filterQueryOption, settings); if (!visited) { throw new ODataException("$filter query must contain ID property"); } }
public void ApplyToEnums_ReturnsCorrectQueryable(string filter, int[] enumModelIds) { // Arrange var builder = new ODataConventionModelBuilder(); builder.EntitySet<EnumModel>("EnumModels"); var model = builder.GetEdmModel(); var context = new ODataQueryContext(model, typeof(EnumModel), "EnumModels"); var filterOption = new FilterQueryOption(filter, context); IEnumerable<EnumModel> enumModels = EnumModelTestData; // Act IQueryable queryable = filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }); // Assert Assert.NotNull(queryable); IEnumerable<EnumModel> actualCustomers = Assert.IsAssignableFrom<IEnumerable<EnumModel>>(queryable); Assert.Equal( enumModelIds, actualCustomers.Select(enumModel => enumModel.Id)); }
public void CanConstructValidAnyQueryOverPrimitiveCollectionProperty() { var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer)); var filter = new FilterQueryOption("Aliases/any(a: a eq 'alias')", context); var node = filter.FilterClause; var anyNode = node.Expression as AnyNode; var aParameter = anyNode.RangeVariables.SingleOrDefault(p => p.Name == "a"); var aParameterType = aParameter.TypeReference.Definition as IEdmPrimitiveType; Assert.NotNull(aParameter); Assert.NotNull(aParameterType); Assert.Equal("a", aParameter.Name); }
/// <summary> /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from /// the <see cref="ODataQueryContext"/>. /// </summary> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param> /// <param name="request">The incoming request message</param> public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request) { if (context == null) { throw Error.ArgumentNull("context"); } if (request == null) { throw Error.ArgumentNull("request"); } // remember the context Context = context; // Parse the query from request Uri RawValues = new ODataRawQueryOptions(); IEnumerable <KeyValuePair <string, string> > queryParameters = request.GetQueryNameValuePairs(); foreach (KeyValuePair <string, string> kvp in queryParameters) { switch (kvp.Key) { case "$filter": RawValues.Filter = kvp.Value; ThrowIfEmpty(kvp.Value, "$filter"); Filter = new FilterQueryOption(kvp.Value, context); break; case "$orderby": RawValues.OrderBy = kvp.Value; ThrowIfEmpty(kvp.Value, "$orderby"); OrderBy = new OrderByQueryOption(kvp.Value, context); break; case "$top": RawValues.Top = kvp.Value; ThrowIfEmpty(kvp.Value, "$top"); Top = new TopQueryOption(kvp.Value, context); break; case "$skip": RawValues.Skip = kvp.Value; ThrowIfEmpty(kvp.Value, "$skip"); Skip = new SkipQueryOption(kvp.Value, context); break; case "$select": RawValues.Select = kvp.Value; break; case "$inlinecount": RawValues.InlineCount = kvp.Value; break; case "$expand": RawValues.Expand = kvp.Value; break; case "$skiptoken": RawValues.SkipToken = kvp.Value; break; default: // we don't throw if we can't recognize the query break; } } }
protected string BindFilter(FilterQueryOption filterQuery) { return BindFilterClause(filterQuery.FilterClause); }
public void ApplyTo_Throws_Null_AssembliesResolver() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filter = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context); // Act & Assert Assert.ThrowsArgumentNull(() => filter.ApplyTo(new Customer[0].AsQueryable(), new ODataQuerySettings(), null), "assembliesResolver"); }
public void CanTurnOffValidationForFilter() { ODataValidationSettings settings = new ODataValidationSettings() { AllowedFunctions = AllowedFunctions.AllDateTimeFunctions }; ODataQueryContext context = ValidationTestHelper.CreateCustomerContext(); FilterQueryOption option = new FilterQueryOption("substring(Name,8,1) eq '7'", context); Assert.Throws<ODataException>(() => option.Validate(settings), "Function 'substring' is not allowed. To allow it, set the 'AllowedFunctions' property on QueryableAttribute or QueryValidationSettings."); option.Validator = null; Assert.DoesNotThrow(() => option.Validate(settings)); }
public void ApplyTo_Returns_Correct_Queryable(string filter, int[] customerIds) { // Arrange var model = new ODataModelBuilder() .Add_Order_EntityType() .Add_Customer_EntityType_With_Address() .Add_CustomerOrders_Relationship() .Add_Customer_EntityType_With_CollectionProperties() .Add_Customers_EntitySet() .GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filterOption = new FilterQueryOption(filter, context); IEnumerable<Customer> customers = CustomerFilterTestData; // Act IQueryable queryable = filterOption.ApplyTo(customers.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }); // Assert Assert.NotNull(queryable); IEnumerable<Customer> actualCustomers = Assert.IsAssignableFrom<IEnumerable<Customer>>(queryable); Assert.Equal( customerIds, actualCustomers.Select(customer => customer.CustomerId)); }
public void ApplyTo_ReturnsCorrectQueryable_PropertyAlias(string filter, int[] propertyAliasIds) { // Arrange var model = GetPropertyAliasModel(); var context = new ODataQueryContext(model, typeof(PropertyAlias)); var filterOption = new FilterQueryOption(filter, context); IEnumerable<PropertyAlias> propertyAliases = PropertyAliasTestData; // Act IQueryable queryable = filterOption.ApplyTo( propertyAliases.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }); // Assert Assert.NotNull(queryable); IEnumerable<PropertyAlias> actualPropertyAliases = Assert.IsAssignableFrom<IEnumerable<PropertyAlias>>(queryable); Assert.Equal( propertyAliasIds, actualPropertyAliases.Select(propertyAlias => propertyAlias.Id)); }
public void ApplyToEnums_ThrowsNotSupported_ForStringFunctions(string filter, string exceptionMessage) { // Arrange var builder = new ODataConventionModelBuilder(); builder.EntitySet<EnumModel>("EnumModels"); var model = builder.GetEdmModel(); var context = new ODataQueryContext(model, typeof(EnumModel), "EnumModels"); var filterOption = new FilterQueryOption(filter, context); IEnumerable<EnumModel> enumModels = EnumModelTestData; // Act Assert.Throws<ODataException>( () => filterOption.ApplyTo(enumModels.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }), exceptionMessage ); }
public void CanConstructValidAnyQueryOverComplexCollectionProperty() { var model = new ODataModelBuilder().Add_Customer_EntityType_With_CollectionProperties().Add_Customers_EntitySet().Add_Address_ComplexType().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var filter = new FilterQueryOption("Addresses/any(a: a/HouseNumber eq 1)", context); var node = filter.QueryNode; var anyNode = node.Expression as AnyQueryNode; var aParameter = anyNode.Parameters.SingleOrDefault(p => p.Name == "a"); var aParameterType = aParameter.ParameterType.Definition as IEdmComplexType; Assert.NotNull(aParameter); // There's currently a bug here. For now, the test checks for the presence of the bug (as a reminder to fix // the test once the bug is fixed). // The following asserts show the behavior with the bug and should be removed once the bug is fixed. Assert.Null(aParameterType); Assert.Equal("a", aParameter.Name); // TODO: Enable once Uri Parser sets parameters of Any/All bound to CollectionProperty correctly // The following asserts show the behavior without the bug, and should be enabled once the bug is fixed. //Assert.NotNull(aParameterType); //Assert.Equal("Address", aParameter.Name); }