internal IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings) { if (query == null) { throw Error.ArgumentNull("query"); } if (querySettings == null) { throw Error.ArgumentNull("querySettings"); } if (Context.ElementClrType == null) { throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo"); } ComputeClause computeClause = ComputeClause; Contract.Assert(computeClause != null); ODataQuerySettings updatedSettings = Context.UpdateQuerySettings(querySettings, query); var binder = new ComputeBinder(updatedSettings, _assembliesResolver, Context.ElementClrType, Context.Model, computeClause.ComputedItems); query = binder.Bind(query); return(query); }
/// <summary> /// Create a new ODataUri. This contains the semantic meaning of the /// entire uri. /// </summary> /// <param name="parameterAliasValueAccessor">The ParameterAliasValueAccessor.</param> /// <param name="path">The top level path for this uri.</param> /// <param name="customQueryOptions">Any custom query options for this uri. Can be null.</param> /// <param name="selectAndExpand">Any $select or $expand option for this uri. Can be null.</param> /// <param name="filter">Any $filter option for this uri. Can be null.</param> /// <param name="orderby">Any $orderby option for this uri. Can be null</param> /// <param name="search">Any $search option for this uri. Can be null</param> /// <param name="apply">Any $apply option for this uri. Can be null</param> /// <param name="skip">Any $skip option for this uri. Can be null.</param> /// <param name="top">Any $top option for this uri. Can be null.</param> /// <param name="index">Any $index for this uri. Can be null.</param> /// <param name="queryCount">Any query $count option for this uri. Can be null.</param> /// <param name="compute">Any query $compute option for this uri. Can be null.</param> internal ODataUri( ParameterAliasValueAccessor parameterAliasValueAccessor, ODataPath path, IEnumerable <QueryNode> customQueryOptions, SelectExpandClause selectAndExpand, FilterClause filter, OrderByClause orderby, SearchClause search, ApplyClause apply, long?skip, long?top, long?index, bool?queryCount, ComputeClause compute = null) { this.ParameterAliasValueAccessor = parameterAliasValueAccessor; this.Path = path; this.CustomQueryOptions = new ReadOnlyCollection <QueryNode>(customQueryOptions.ToList()); this.SelectAndExpand = selectAndExpand; this.Filter = filter; this.OrderBy = orderby; this.Search = search; this.Apply = apply; this.Skip = skip; this.Top = top; this.Index = index; this.QueryCount = queryCount; this.Compute = compute; }
/// <summary>Translates a <see cref="ComputeClause"/> into a string.</summary> /// <param name="computeClause">The compute clause to translate.</param> /// <returns>The translated String.</returns> internal string TranslateComputeClause(ComputeClause computeClause) { Debug.Assert(computeClause != null, "computeClause != null"); bool appendComma = false; StringBuilder sb = new StringBuilder(); foreach (var item in computeClause.ComputedItems) { if (appendComma) { sb.Append(ExpressionConstants.SymbolComma); } else { appendComma = true; } sb.Append(this.TranslateNode(item.Expression)); sb.Append(ExpressionConstants.SymbolEscapedSpace); // "%20" sb.Append(ExpressionConstants.KeywordAs); sb.Append(ExpressionConstants.SymbolEscapedSpace); // "%20" sb.Append(item.Alias); } return(sb.ToString()); }
private void BuildCompute(ComputeClause computeClause) { foreach (ComputeExpression computeExpression in computeClause.ComputedItems) { Expression expression = _visitor.TranslateNode(computeExpression.Expression); IEdmTypeReference edmTypeReference = OeEdmClrHelper.GetEdmTypeReference(_visitor.EdmModel, expression.Type); _navigationItem.AddSelectItem(new OeSelectItem(new ComputeProperty(computeExpression.Alias, edmTypeReference, expression), false)); } }
private void BuildCompute(ComputeClause computeClause) { foreach (ComputeExpression computeExpression in computeClause.ComputedItems) { Expression expression = _visitor.TranslateNode(computeExpression.Expression); IEdmTypeReference edmTypeReference = OeEdmClrHelper.GetEdmTypeReference(_model, expression.Type); _selectItemInfos.Add(new SelectItemInfo(new ComputeProperty(computeExpression.Alias, edmTypeReference), expression)); } }
public void ComputeOptionSetCorrectly() { // Arrange & Act ComputeClause compute = new ComputeClause(null); PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, null, null, null, null, compute); // Assert Assert.NotNull(select.ComputeOption); Assert.Same(compute, select.ComputeOption); }
/// <summary> /// Validates a <see cref="ComputeClause" />. /// </summary> /// <param name="computeClause">The <see cref="ComputeClause" />.</param> /// <param name="settings">The validation settings.</param> /// <param name="model">The EdmModel.</param> /// <remarks> /// Please note this method is not thread safe. /// </remarks> public virtual void Validate(ComputeClause computeClause, ODataValidationSettings settings, IEdmModel model) { CurrentAnyAllExpressionDepth = 0; CurrentNodeCount = 0; base.Model = model; foreach (ComputeExpression computeITem in computeClause.ComputedItems) { ValidateQueryNode(computeITem.Expression, settings); } }
internal void SetComputedProperties(ComputeClause computeClause) { if (computeClause == null || !computeClause.ComputedItems.Any()) { return; } foreach (var item in computeClause.ComputedItems) { ComputedProperties.Add(item.Alias); } }
private void ValidateComputeClause(ComputeClause compute, ODataUrlValidationContext validationContext) { if (compute != null) { ValidateItem(compute, validationContext); foreach (ComputeExpression computeExpression in compute.ComputedItems) { ValidateItem(computeExpression, validationContext); validationContext.ExpressionValidator.ValidateNode(computeExpression.Expression); } } }
private void BuildCompute(ComputeClause computeClause) { if (computeClause != null) { foreach (ComputeExpression computeExpression in computeClause.ComputedItems) { Expression expression = _joinBuilder.Visitor.TranslateNode(computeExpression.Expression); IEdmTypeReference edmTypeReference = OeEdmClrHelper.GetEdmTypeReference(_edmModel, expression.Type); var computeProperty = new ComputeProperty(computeExpression.Alias, edmTypeReference, expression); _rootNavigationItem.AddStructuralItem(computeProperty, false); } } }
private bool CompareCompute(ComputeClause clause1, ComputeClause clause2) { if (clause1 == clause2) { return(true); } if (clause1 == null || clause2 == null) { return(false); } return(EnumerableComparer.Compare(clause1.ComputedItems, clause2.ComputedItems, CompareComputeExpression)); }
public void CtorComputeQueryOption_GetQueryNodeParsesQuery() { // Arrange IEdmModel model = _model; ODataQueryContext context = new ODataQueryContext(model, typeof(ComputeCustomer)) { RequestContainer = new MockServiceProvider() }; // Act ComputeQueryOption compute = new ComputeQueryOption("Price mul Qty as Total,Price mul 2.0 as Tax", context); ComputeClause computeClause = compute.ComputeClause; // Assert Assert.Equal(2, computeClause.ComputedItems.Count()); Assert.Collection(computeClause.ComputedItems, e => { Assert.Equal("Total", e.Alias); Assert.Equal(QueryNodeKind.BinaryOperator, e.Expression.Kind); BinaryOperatorNode binaryNode = e.Expression as BinaryOperatorNode; Assert.Equal(BinaryOperatorKind.Multiply, binaryNode.OperatorKind); Assert.Equal(QueryNodeKind.Convert, binaryNode.Right.Kind); ConvertNode convertNode = (ConvertNode)binaryNode.Right; Assert.Equal("Qty", ((SingleValuePropertyAccessNode)convertNode.Source).Property.Name); Assert.Equal(QueryNodeKind.SingleValuePropertyAccess, binaryNode.Left.Kind); var propertyAccessNode = binaryNode.Left as SingleValuePropertyAccessNode; Assert.Equal("Price", propertyAccessNode.Property.Name); }, e => { Assert.Equal("Tax", e.Alias); Assert.Equal(QueryNodeKind.BinaryOperator, e.Expression.Kind); BinaryOperatorNode binaryNode = e.Expression as BinaryOperatorNode; Assert.Equal(BinaryOperatorKind.Multiply, binaryNode.OperatorKind); Assert.Equal(QueryNodeKind.Constant, binaryNode.Right.Kind); Assert.Equal(2.0, ((ConstantNode)binaryNode.Right).Value); Assert.Equal(QueryNodeKind.SingleValuePropertyAccess, binaryNode.Left.Kind); var propertyAccessNode = binaryNode.Left as SingleValuePropertyAccessNode; Assert.Equal("Price", propertyAccessNode.Property.Name); }); }
public ApplyClause BindApply(IEnumerable <QueryToken> tokens) { ExceptionUtils.CheckArgumentNotNull(tokens, "tokens"); var transformations = new List <TransformationNode>(); foreach (var token in tokens) { switch (token.Kind) { case QueryTokenKind.Aggregate: AggregateTransformationNode aggregate = BindAggregateToken((AggregateToken)(token)); transformations.Add(aggregate); aggregateExpressionsCache = aggregate.Expressions; state.AggregatedPropertyNames = aggregate.Expressions.Select(statement => statement.Alias).ToList(); break; case QueryTokenKind.AggregateGroupBy: GroupByTransformationNode groupBy = BindGroupByToken((GroupByToken)(token)); transformations.Add(groupBy); break; case QueryTokenKind.Compute: ComputeClause computeClause = this.computeBinder.BindCompute((ComputeToken)token); ComputeTransformationNode computeNode = new ComputeTransformationNode(computeClause); transformations.Add(computeNode); state.AggregatedPropertyNames = computeNode.ComputeClause.ComputedItems.Select(statement => statement.Alias).ToList(); break; default: FilterClause filterClause = this.filterBinder.BindFilter(token); FilterTransformationNode filterNode = new FilterTransformationNode(filterClause); transformations.Add(filterNode); break; } } return(new ApplyClause(transformations)); }
public void ParseComputeAsQueryOption() { // Create model EdmModel model = new EdmModel(); EdmEntityType elementType = model.AddEntityType("DevHarness", "Entity"); EdmTypeReference typeReference = new EdmStringTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.String), false); elementType.AddProperty(new EdmStructuralProperty(elementType, "Prop1", typeReference)); EdmEntityContainer container = model.AddEntityContainer("Default", "Container"); container.AddEntitySet("Entities", elementType); // Define queries and new up parser. Uri root = new Uri("http://host"); Uri url = new Uri("http://host/Entities?$compute=cast(Prop1, 'Edm.String') as Property1AsString, tolower(Prop1) as Property1Lower"); ODataUriParser parser = new ODataUriParser(model, root, url); // parse and validate ComputeClause clause = parser.ParseCompute(); List <ComputeExpression> items = clause.ComputedItems.ToList(); items.Count().Should().Be(2); items[0].Alias.ShouldBeEquivalentTo("Property1AsString"); items[0].Expression.ShouldBeSingleValueFunctionCallQueryNode(); items[0].Expression.TypeReference.ShouldBeEquivalentTo(typeReference); items[1].Alias.ShouldBeEquivalentTo("Property1Lower"); items[1].Expression.ShouldBeSingleValueFunctionCallQueryNode(); items[1].Expression.TypeReference.FullName().ShouldBeEquivalentTo("Edm.String"); items[1].Expression.TypeReference.IsNullable.ShouldBeEquivalentTo(true); // tolower is built in function that allows nulls. ComputeExpression copy = new ComputeExpression(items[0].Expression, items[0].Alias, null); copy.Expression.Should().NotBeNull(); copy.TypeReference.Should().BeNull(); ComputeClause varied = new ComputeClause(null); }
public Expression Build(Expression source, OeQueryContext queryContext) { OrderByClause orderBy = queryContext.ODataUri.OrderBy; SelectExpandClause selectAndExpand = queryContext.ODataUri.SelectAndExpand; ComputeClause compute = queryContext.ODataUri.Compute; if (selectAndExpand != null) { BuildSelect(selectAndExpand, source, _visitor.Parameter, queryContext.MetadataLevel, queryContext.NavigationNextLink); } if (compute != null) { BuildCompute(compute); } if (orderBy != null) { BuildOrderBy(orderBy); } if (_selectItemInfos.Count == 0 && queryContext.SkipTokenParser != null) { queryContext.SkipTokenParser.Accessors = GetAccessors(source, orderBy); return(null); } var selectExpression = CreateSelectExpression(source, _visitor.Parameter); if (queryContext.SkipTokenParser != null) { queryContext.SkipTokenParser.Accessors = GetAccessors(selectExpression, orderBy); } return(selectExpression); }
public override void Visit(ComputeClause node) { this.action(node); }
/// <summary> /// Create a ComputeTransformationNode. /// </summary> /// <param name="ComputeClause">A <see cref="ComputeClause"/> representing the metadata bound Compute expression.</param> public ComputeTransformationNode(ComputeClause computeClause) { ExceptionUtils.CheckArgumentNotNull(computeClause, "computeClause"); this.computeClause = computeClause; }
public override void ExplicitVisit(ComputeClause fragment) { _fragments.Add(fragment); }
public void ParseComputeAsLevel2ExpandQueryOption() { // Create model EdmModel model = new EdmModel(); EdmEntityType elementType = model.AddEntityType("DevHarness", "Entity"); EdmEntityType targetType = model.AddEntityType("DevHarness", "Navigation"); EdmEntityType subTargetType = model.AddEntityType("DevHarness", "SubNavigation"); EdmTypeReference typeReference = new EdmStringTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.String), false); elementType.AddProperty(new EdmStructuralProperty(elementType, "Prop1", typeReference)); targetType.AddProperty(new EdmStructuralProperty(targetType, "Prop1", typeReference)); subTargetType.AddProperty(new EdmStructuralProperty(subTargetType, "Prop1", typeReference)); EdmNavigationPropertyInfo propertyInfo = new EdmNavigationPropertyInfo(); propertyInfo.Name = "Nav1"; propertyInfo.Target = targetType; propertyInfo.TargetMultiplicity = EdmMultiplicity.One; EdmProperty navigation = EdmNavigationProperty.CreateNavigationProperty(elementType, propertyInfo); elementType.AddProperty(navigation); EdmNavigationPropertyInfo subPropertyInfo = new EdmNavigationPropertyInfo(); subPropertyInfo.Name = "SubNav1"; subPropertyInfo.Target = subTargetType; subPropertyInfo.TargetMultiplicity = EdmMultiplicity.One; EdmProperty subnavigation = EdmNavigationProperty.CreateNavigationProperty(targetType, subPropertyInfo); targetType.AddProperty(subnavigation); EdmEntityContainer container = model.AddEntityContainer("Default", "Container"); container.AddEntitySet("Entities", elementType); // Define queries and new up parser. string address = "http://host/Entities?$compute=cast(Prop1, 'Edm.String') as Property1AsString, tolower(Prop1) as Property1Lower&" + "$expand=Nav1($compute=cast(Prop1, 'Edm.String') as NavProperty1AsString;" + "$expand=SubNav1($compute=cast(Prop1, 'Edm.String') as SubNavProperty1AsString))"; Uri root = new Uri("http://host"); Uri url = new Uri(address); ODataUriParser parser = new ODataUriParser(model, root, url); // parse ComputeClause computeClause = parser.ParseCompute(); SelectExpandClause selectClause = parser.ParseSelectAndExpand(); // validate top compute List <ComputeExpression> items = computeClause.ComputedItems.ToList(); items.Count().Should().Be(2); items[0].Alias.ShouldBeEquivalentTo("Property1AsString"); items[0].Expression.ShouldBeSingleValueFunctionCallQueryNode(); items[0].Expression.TypeReference.ShouldBeEquivalentTo(typeReference); items[1].Alias.ShouldBeEquivalentTo("Property1Lower"); items[1].Expression.ShouldBeSingleValueFunctionCallQueryNode(); items[1].Expression.TypeReference.FullName().ShouldBeEquivalentTo("Edm.String"); items[1].Expression.TypeReference.IsNullable.ShouldBeEquivalentTo(true); // tolower is built in function that allows nulls. // validate level 1 expand compute List <SelectItem> selectItems = selectClause.SelectedItems.ToList(); selectItems.Count.Should().Be(1); ExpandedNavigationSelectItem expanded = selectItems[0] as ExpandedNavigationSelectItem; List <ComputeExpression> computes = expanded.ComputeOption.ComputedItems.ToList(); computes.Count.Should().Be(1); computes[0].Alias.ShouldBeEquivalentTo("NavProperty1AsString"); computes[0].Expression.ShouldBeSingleValueFunctionCallQueryNode(); computes[0].Expression.TypeReference.ShouldBeEquivalentTo(typeReference); // validate level 2 expand compute List <SelectItem> subSelectItems = expanded.SelectAndExpand.SelectedItems.ToList(); subSelectItems.Count.Should().Be(1); ExpandedNavigationSelectItem subExpanded = subSelectItems[0] as ExpandedNavigationSelectItem; List <ComputeExpression> subComputes = subExpanded.ComputeOption.ComputedItems.ToList(); subComputes.Count.Should().Be(1); subComputes[0].Alias.ShouldBeEquivalentTo("SubNavProperty1AsString"); subComputes[0].Expression.ShouldBeSingleValueFunctionCallQueryNode(); subComputes[0].Expression.TypeReference.ShouldBeEquivalentTo(typeReference); }