public static List <QueryEntity> CherryPickSelectedProperties <TQueryableEntity>( this IEnumerable <QueryEntity> entities, QueryClause <TQueryableEntity> query, RepositoryEntityMetadata metadata, IEnumerable <string> includeAdditionalProperties = null) where TQueryableEntity : IQueryableEntity { var selectedPropertyNames = query.GetAllSelectedFields(); if (!selectedPropertyNames.Any()) { return(entities.ToList()); } selectedPropertyNames = selectedPropertyNames .Concat(new[] { nameof(QueryEntity.Id) }) .Concat(includeAdditionalProperties ?? Enumerable.Empty <string>()) .ToList(); return(entities .Select(resultEntity => resultEntity.Properties .Where(resultEntityProperty => selectedPropertyNames.Contains(resultEntityProperty.Key))) .Select(selectedProperties => EntityFromContainerProperties(selectedProperties.ToObjectDictionary(), metadata)) .ToList()); }
public static int GetDefaultSkip <TQueryableEntity>(this QueryClause <TQueryableEntity> query) where TQueryableEntity : IQueryableEntity { return(query.ResultOptions.Offset != ResultOptions.DefaultOffset ? query.ResultOptions.Offset : 0); }
public void TestPerformQuery() { List <QueryClause> clauses = new List <QueryClause>(); QueryClause q = new QueryClause() { BooleanOperator = "OR", ComparisonOperator = "=", DataType = SqlDbType.Int, FieldName = "IssueCategoryId", FieldValue = null }; clauses.Add(q); q = new QueryClause() { BooleanOperator = "AND", ComparisonOperator = "<>", DataType = SqlDbType.Int, FieldName = "IssueStatusId", FieldValue = "3" }; clauses.Add(q); List <Issue> results = IssueManager.PerformQuery(clauses, 96); foreach (Issue result in results) { Console.WriteLine("Id: {1}; Title: {0}", result.Title, result.Id); } Assert.IsTrue(results.Count > 0); }
/// <summary> /// Initializes a new instance of the CodeWalker class. /// </summary> /// <param name="queryClause">The query clause to walk through.</param> /// <param name="statementCallback">Callback executed when a statement is visited.</param> /// <param name="expressionCallback">Callback executed when an expression is visited.</param> /// <param name="queryClauseCallback">Callback executed when a query clause is visited.</param> /// <param name="context">The optional visitor context data.</param> private CodeWalker( QueryClause queryClause, CodeWalkerStatementVisitor <T> statementCallback, CodeWalkerExpressionVisitor <T> expressionCallback, CodeWalkerQueryClauseVisitor <T> queryClauseCallback, T context) { Param.AssertNotNull(queryClause, "queryClause"); Param.Ignore(statementCallback); Param.Ignore(expressionCallback); Param.Ignore(queryClauseCallback); Param.Ignore(context); this.statementCallback = statementCallback; this.expressionCallback = expressionCallback; this.queryClauseCallback = queryClauseCallback; this.WalkQueryClause( queryClause, queryClause.ParentQueryClause, queryClause.FindParentExpression(), queryClause.FindParentStatement(), queryClause.FindParentElement(), context); }
private List <QueryEntity> QueryPrimaryEntities <TQueryableEntity>(IRedisClient client, string containerName, QueryClause <TQueryableEntity> query, RepositoryEntityMetadata metadata) where TQueryableEntity : IQueryableEntity { var primaryEntities = GetRowKeys(client, containerName) .ToDictionary(key => key, key => GetEntityFromContainer(client, key, metadata)); var orderByExpression = query.ToDynamicLinqOrderByClause(); var primaryEntitiesDynamic = primaryEntities.AsQueryable() .OrderBy(orderByExpression) .Skip(query.GetDefaultSkip()) .Take(query.GetDefaultTake(this)); if (!query.Wheres.Any()) { return(primaryEntitiesDynamic .Select(ped => QueryEntity.FromProperties(ped.Value, metadata)) .ToList()); } var queryExpression = query.Wheres.ToDynamicLinqWhereClause(); return(primaryEntitiesDynamic .Where(queryExpression) .Select(ped => QueryEntity.FromProperties(ped.Value, metadata)) .ToList()); }
public void FilterBinder_BindsComputedPropertyInDollarFilter_FromDollarCompute() { // Arrange QueryClause clause = CreateQueryClause("$filter=Total lt 30&$compute=Price mul Qty as Total", _model, typeof(ComputeCustomer)); ODataQuerySettings querySettings = new ODataQuerySettings(); IFilterBinder binder = new FilterBinder(); QueryBinderContext context = new QueryBinderContext(_model, querySettings, typeof(ComputeCustomer)); if (clause.Compute != null) { context.AddComputedProperties(clause.Compute.ComputedItems); } // Act Expression filterExp = binder.BindFilter(clause.Filter, context); // Assert string resultExpression = ExpressionStringBuilder.ToString(filterExp); Assert.Equal("$it => (Convert(($it.Price * Convert($it.Qty))) < Convert(30))", resultExpression); Assert.True(FilterBinderTests.InvokeFilter(new ComputeCustomer { Price = 10, Qty = 2 }, filterExp)); Assert.False(FilterBinderTests.InvokeFilter(new ComputeCustomer { Price = 10, Qty = 4 }, filterExp)); }
/// <summary> /// Visits one code unit in the document. /// </summary> /// <param name="codeUnit">The item being visited.</param> /// <param name="parentElement">The parent element, if any.</param> /// <param name="parentStatement">The parent statement, if any.</param> /// <param name="parentExpression">The parent expression, if any.</param> /// <param name="parentClause">The parent query clause, if any.</param> /// <param name="parentToken">The parent token, if any.</param> /// <param name="context">The context.</param> /// <returns>Returns true to continue, or false to stop the walker.</returns> private bool VisitCodeUnit( CodeUnit codeUnit, Element parentElement, Statement parentStatement, Expression parentExpression, QueryClause parentClause, Token parentToken, object context) { Param.AssertNotNull(codeUnit, "codeUnit"); Param.Ignore(parentElement, parentStatement, parentExpression, parentClause, parentToken); Param.Ignore(context); if (codeUnit.CodeUnitType == CodeUnitType.Element) { return(this.VisitElement((Element)codeUnit, parentElement)); } else if (codeUnit.CodeUnitType == CodeUnitType.Statement) { return(this.VisitStatement((Statement)codeUnit, parentExpression, parentStatement, parentElement)); } else if (codeUnit.CodeUnitType == CodeUnitType.Expression) { return(this.VisitExpression((Expression)codeUnit, parentExpression, parentStatement, parentElement)); } return(!this.Cancel); }
public static string GetDefaultOrdering <TQueryableEntity>(this QueryClause <TQueryableEntity> query) where TQueryableEntity : IQueryableEntity { var by = query.ResultOptions.OrderBy.By; if (!by.HasValue()) { by = DefaultOrderingPropertyName; } var selectedFields = query.GetAllSelectedFields(); if (selectedFields.Any()) { return(selectedFields.Contains(by) ? by : selectedFields.Contains(BackupOrderingPropertyName) ? BackupOrderingPropertyName : selectedFields.First()); } return(HasProperty <TQueryableEntity>(by) ? by : HasProperty <TQueryableEntity>(BackupOrderingPropertyName) ? BackupOrderingPropertyName : FirstProperty <TQueryableEntity>()); }
public List <QueryEntity> Query <TQueryableEntity>(string containerName, QueryClause <TQueryableEntity> query, RepositoryEntityMetadata metadata) where TQueryableEntity : IQueryableEntity { if (query == null || query.Options.IsEmpty) { return(new List <QueryEntity>()); } var container = EnsureContainer(containerName); try { var primaryResults = QueryPrimaryResults(query, container, containerName); var joinedTables = query.JoinedEntities .Where(je => je.Join != null) .ToDictionary(je => je.EntityName, je => new { Collection = QueryJoiningContainer(je, primaryResults.Select(e => e[je.Join.Left.JoinedFieldName])), JoinedEntity = je }); var primaryEntities = primaryResults .ConvertAll(r => QueryEntity.FromProperties(r.FromContainerEntity(metadata), metadata)); if (joinedTables.Any()) { foreach (var joinedTable in joinedTables) { var joinedEntity = joinedTable.Value.JoinedEntity; var join = joinedEntity.Join; var leftEntities = primaryEntities.ToDictionary(e => e.Id.ToString(), e => e.Properties); var rightEntities = joinedTable.Value.Collection.ToDictionary( e => e[IdentifierPropertyName].Value <string>(), e => e.FromContainerEntity( RepositoryEntityMetadata.FromType(join.Right.EntityType))); primaryEntities = join .JoinResults(leftEntities, rightEntities, metadata, joinedEntity.Selects.ProjectSelectedJoinedProperties()); } } return(primaryEntities.CherryPickSelectedProperties(query, metadata, new[] { IdentifierPropertyName })); } catch (CosmosException ex) { if (ex.StatusCode == HttpStatusCode.NotFound) { return(new List <QueryEntity>()); } throw; } }
public static int GetDefaultTake <TQueryableEntity>(this QueryClause <TQueryableEntity> query, IRepository repository) where TQueryableEntity : IQueryableEntity { return(query.ResultOptions.Limit == ResultOptions.DefaultLimit ? repository.MaxQueryResults : query.ResultOptions.Limit); }
private void TranslateCombinedQuery(QueryClause clause, BooleanQuery booleanQuery) { var translatedQuery = this.Translate(clause.Query); if (translatedQuery.IsNotNull()) { booleanQuery.Add(translatedQuery, this.GetOccur(clause.Occurance)); } }
public static bool HasAnyJoins <TEntity>(this QueryClause <TEntity> query) where TEntity : IQueryableEntity { query.GuardAgainstNull(nameof(query)); return(query.JoinedEntities .Any(je => je.Join.Exists())); }
public void Add(string Q, string Key, Operator Operator, object Value) { if (!el.ContainsKey(Q)) { QueryClause clause = new QueryClause(Key, Operator, Value); el.Add(Q, clause); } }
private List <JObject> QueryPrimaryResults <TQueryableEntity>(QueryClause <TQueryableEntity> query, Container container, string containerName) where TQueryableEntity : IQueryableEntity { var containerQuery = new QueryDefinition(query.ToAzureCosmosSqlApiQueryClause(containerName, this)); return(container.GetItemQueryIterator <object>(containerQuery) .ToList()); }
public static string ToDynamicLinqOrderByClause <TQueryableEntity>(this QueryClause <TQueryableEntity> query) where TQueryableEntity : IQueryableEntity { var orderBy = query.GetDefaultOrdering().ToDynamicLinqFieldName(); orderBy = $"{orderBy}{(query.ResultOptions.OrderBy.Direction == OrderDirection.Descending ? " DESC" : "")}"; return(orderBy); }
bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery) { if (!IsTransparentIdentifier(fromClause.Identifier)) { return(false); } Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last()); if (!match.Success) { return(false); } QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last(); NamedArgumentExpression nae1 = match.Get <NamedArgumentExpression>("nae1").Single(); NamedArgumentExpression nae2 = match.Get <NamedArgumentExpression>("nae2").Single(); if (nae1.Identifier != ((IdentifierExpression)nae1.Expression).Identifier) { return(false); } IdentifierExpression nae2IdentExpr = nae2.Expression as IdentifierExpression; if (nae2IdentExpr != null && nae2.Identifier == nae2IdentExpr.Identifier) { // from * in (from x in ... select new { x = x, y = y }) ... // => // from x in ... ... fromClause.Remove(); selectClause.Remove(); // Move clauses from innerQuery to query QueryClause insertionPos = null; foreach (var clause in innerQuery.Clauses) { query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach()); } } else { // from * in (from x in ... select new { x = x, y = expr }) ... // => // from x in ... let y = expr ... fromClause.Remove(); selectClause.Remove(); // Move clauses from innerQuery to query QueryClause insertionPos = null; foreach (var clause in innerQuery.Clauses) { query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach()); } query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = nae2.Identifier, Expression = nae2.Expression.Detach() }); } return(true); }
/// <summary> /// This method adds a new query clause to the user interface. /// </summary> /// <param name="bindData">if set to <c>true</c> [bind data].</param> /// <param name="queryClause"></param> void AddClause(bool bindData = false, QueryClause queryClause = null) { var ctlPickQueryField = (PickQueryField)Page.LoadControl("~/UserControls/PickQueryField.ascx"); plhClauses.Controls.Add(ctlPickQueryField); ctlPickQueryField.ProjectId = ProjectId; if (bindData) { ctlPickQueryField.QueryClause = queryClause; } }
protected CollectionBase GenerateQueryClauseCollectionFromReader(IDataReader returnData) { QueryClauseCollection queryCollection = new QueryClauseCollection(); while (returnData.Read()) { QueryClause newQueryClause = new QueryClause((string)returnData["BooleanOperator"], (string)returnData["FieldName"], (string)returnData["ComparisonOperator"], (string)returnData["FieldValue"], (SqlDbType)returnData["DataType"]); queryCollection.Add(newQueryClause); } return(queryCollection); }
public void SelectExpandBinder_BindsComputedPropertyInSelect_FromDollarCompute() { // Arrange QueryClause clause = CreateQueryClause("$select=Name,Total&$compute=Price mul Qty as Total", _model, typeof(ComputeCustomer)); ODataQuerySettings querySettings = new ODataQuerySettings(); SelectExpandBinder binder = new SelectExpandBinder(); QueryBinderContext context = new QueryBinderContext(_model, querySettings, typeof(ComputeCustomer)); if (clause.Compute != null) { context.AddComputedProperties(clause.Compute.ComputedItems); } // Act Expression selectExp = binder.BindSelectExpand(clause.SelectExpand, context); // Assert Assert.NotNull(selectExp); string resultExpression = ExpressionStringBuilder.ToString(selectExp); Assert.Equal("$it => new SelectSome`1() {" + "Model = Microsoft.OData.Edm.EdmModel, " + "Container = new NamedPropertyWithNext1`1() {" + "Name = Name, " + "Value = $it.Name, " + "Next0 = new NamedProperty`1() {" + "Name = Total, " + "Value = ($it.Price * Convert($it.Qty)), " + "}, " + "Next1 = new AutoSelectedNamedProperty`1() {" + "Name = Id, " + "Value = Convert($it.Id), " + "}, }, }", resultExpression); ComputeCustomer customer = new ComputeCustomer { Name = "Peter", Price = 1.99, Qty = 3 }; IDictionary <string, object> result = SelectExpandBinderTest.InvokeSelectExpand(customer, selectExp); Assert.Equal(2, result.Count); Assert.Collection(result, e => { Assert.Equal("Name", e.Key); Assert.Equal("Peter", e.Value); }, e => { Assert.Equal("Total", e.Key); Assert.Equal(5.97, e.Value); }); }
private static List <string> GetAllSelectedFields <TQueryableEntity>(this QueryClause <TQueryableEntity> query) where TQueryableEntity : IQueryableEntity { var primarySelects = query.PrimaryEntity.Selects; var joinedSelects = query.JoinedEntities.SelectMany(je => je.Selects); return(primarySelects .Select(select => select.FieldName) .Concat(joinedSelects.Select(select => select.FieldName)) .ToList()); }
bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, Dictionary <string, object> letClauses) { if (!IsTransparentIdentifier(fromClause.Identifier)) { return(false); } QuerySelectClause selectClause = innerQuery.Clauses.Last() as QuerySelectClause; Match match = selectTransparentIdentifierPattern.Match(selectClause); if (!match.Success) { return(false); } // from * in (from x in ... select new { members of anonymous type }) ... // => // from x in ... { let x = ... } ... fromClause.Remove(); selectClause.Remove(); // Move clauses from innerQuery to query QueryClause insertionPos = null; foreach (var clause in innerQuery.Clauses) { query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach()); } foreach (var expr in match.Get <Expression>("expr")) { switch (expr) { case IdentifierExpression identifier: // nothing to add continue; case NamedExpression namedExpression: if (namedExpression.Expression is IdentifierExpression identifierExpression && namedExpression.Name == identifierExpression.Identifier) { letClauses[namedExpression.Name] = identifierExpression.Annotation <ILVariableResolveResult>(); continue; } QueryLetClause letClause = new QueryLetClause { Identifier = namedExpression.Name, Expression = namedExpression.Expression.Detach() }; var annotation = new LetIdentifierAnnotation(); letClause.AddAnnotation(annotation); letClauses[namedExpression.Name] = annotation; query.Clauses.InsertAfter(insertionPos, letClause); break; } } return(true); }
public void SelectExpandBinder_BindsComputedPropertyInNestedSelect_FromDollarCompute() { // Arrange QueryClause clause = CreateQueryClause("$select=Location($select=StateCode;$compute=Zipcode div 1000 as StateCode)", _model, typeof(ComputeCustomer)); ODataQuerySettings querySettings = new ODataQuerySettings(); SelectExpandBinder binder = new SelectExpandBinder(); QueryBinderContext context = new QueryBinderContext(_model, querySettings, typeof(ComputeCustomer)); if (clause.Compute != null) { context.AddComputedProperties(clause.Compute.ComputedItems); } // Act Expression selectExp = binder.BindSelectExpand(clause.SelectExpand, context); // Assert Assert.NotNull(selectExp); string resultExpression = ExpressionStringBuilder.ToString(selectExp); Assert.Equal("$it => new SelectSome`1() {" + "Model = Microsoft.OData.Edm.EdmModel, " + "Container = new NamedPropertyWithNext0`1() {" + "Name = Location, " + "Value = new SelectSome`1() {" + "Model = Microsoft.OData.Edm.EdmModel, " + "Container = new NamedProperty`1() {" + "Name = StateCode, " + "Value = ($it.Location.Zipcode / 1000), " + "}, " + "}, " + "Next0 = new AutoSelectedNamedProperty`1() {Name = Id, Value = Convert($it.Id), }, }, }", resultExpression); ComputeCustomer customer = new ComputeCustomer { Location = new ComputeAddress { Zipcode = 98029 } }; IDictionary <string, object> result = SelectExpandBinderTest.InvokeSelectExpand(customer, selectExp); var location = Assert.Single(result); Assert.Equal("Location", location.Key); SelectExpandWrapper itemWrapper = location.Value as SelectExpandWrapper; IDictionary <string, object> locationResult = itemWrapper.ToDictionary(); var stateCode = Assert.Single(locationResult); Assert.Equal("StateCode", stateCode.Key); Assert.Equal(98, stateCode.Value); }
private Dictionary <string, IReadOnlyDictionary <string, object> > QueryPrimaryEntities <TQueryableEntity>( string containerName, Container container, QueryClause <TQueryableEntity> query, RepositoryEntityMetadata metadata) where TQueryableEntity : IQueryableEntity { var filter = query.PrimaryEntity.Selects.ToCosmosSqlApiSelectClause(containerName); this.recorder.TraceInformation($"Executed SQL statement: {filter}"); return(container.GetItemQueryIterator <object>(new QueryDefinition(filter)) .ToList() .ToDictionary(jObj => jObj.Property(IdentifierPropertyName).Value.ToString(), jObj => jObj.FromContainerEntity(metadata))); }
//********************************************************************* // // BuildQuery Method // // This method builds a database query by iterating through each query clause. // //****************************************************************** QueryClauseCollection BuildQuery() { QueryClauseCollection colQueryClauses = new QueryClauseCollection(); foreach (PickQueryField ctlPickQuery in plhClauses.Controls) { QueryClause objQueryClause = ctlPickQuery.QueryClause; if (objQueryClause != null) { colQueryClauses.Add(objQueryClause); } } return(colQueryClauses); }
public QueryResults <TDto> Query(QueryClause <TDto> query) { if (query == null || query.Options.IsEmpty) { this.logger.LogDebug("No entities were retrieved from repository, the query is empty"); return(new QueryResults <TDto>(new List <TDto>())); } var entities = this.repository.Query(this.containerName, query, RepositoryEntityMetadata.FromType <TDto>()); this.logger.LogDebug($"{entities.Count} Entities were retrieved from repository"); return(new QueryResults <TDto>(entities.ConvertAll(x => x.ToEntity <TDto>(this.domainFactory)))); }
/// <summary> /// Visits one code unit in the document. /// </summary> /// <param name="codeUnit">The item being visited.</param> /// <param name="parentElement">The parent element, if any.</param> /// <param name="parentStatement">The parent statement, if any.</param> /// <param name="parentExpression">The parent expression, if any.</param> /// <param name="parentClause">The parent query clause, if any.</param> /// <param name="parentToken">The parent token, if any.</param> /// <param name="settings">The settings.</param> /// <returns>Returns true to continue, or false to stop the walker.</returns> private bool VisitCodeUnit( CodeUnit codeUnit, Element parentElement, Statement parentStatement, Expression parentExpression, QueryClause parentClause, Token parentToken, Settings settings) { Param.AssertNotNull(codeUnit, "codeUnit"); Param.Ignore(parentElement, parentStatement, parentExpression, parentClause, parentToken); Param.AssertNotNull(settings, "settings"); if (codeUnit.CodeUnitType == CodeUnitType.Element) { return(this.VisitElement((Element)codeUnit, settings)); } else if (codeUnit.CodeUnitType == CodeUnitType.Expression) { return(this.VisitExpression((Expression)codeUnit, parentElement)); } else if (codeUnit.Is(LexicalElementType.Token)) { Token token = (Token)codeUnit; if (token.TokenType == TokenType.Type && !token.Parent.Is(TokenType.Type)) { // Check that the type is using the built-in types, if applicable. this.CheckBuiltInType((TypeToken)token, parentElement); } else if (token.TokenType == TokenType.String) { // Check that the string is not using the empty string "" syntax. this.CheckEmptyString(token, parentElement); } } else if (codeUnit.Is(PreprocessorType.Region)) { this.CheckRegion((RegionDirective)codeUnit, parentElement, settings); } else if (codeUnit.Is(LexicalElementType.Comment)) { this.CheckForEmptyComments((Comment)codeUnit, parentElement); } return(!this.Cancel); }
public List <QueryEntity> Query <TQueryableEntity>(string containerName, QueryClause <TQueryableEntity> query, RepositoryEntityMetadata metadata) where TQueryableEntity : IQueryableEntity { if (query == null || query.Options.IsEmpty) { return(new List <QueryEntity>()); } var client = EnsureClient(); if (!Exists(client, containerName)) { return(new List <QueryEntity>()); } var primaryEntities = QueryPrimaryEntities(client, containerName, query, metadata); var joinedContainers = query.JoinedEntities .Where(je => je.Join != null) .ToDictionary(je => je.EntityName, je => new { Collection = QueryJoiningContainer(client, je), JoinedEntity = je }); if (joinedContainers.Any()) { foreach (var joinedContainer in joinedContainers) { var joinedEntity = joinedContainer.Value.JoinedEntity; var join = joinedEntity.Join; var leftEntities = primaryEntities .ToDictionary(e => e.Id.ToString(), e => e.Properties); var rightEntities = joinedContainer.Value.Collection .ToDictionary(e => e.Key, e => e.Value.Properties); primaryEntities = join .JoinResults(leftEntities, rightEntities, metadata, joinedEntity.Selects.ProjectSelectedJoinedProperties()); } } return(primaryEntities.CherryPickSelectedProperties(query, metadata)); }
/// <summary> /// Processes the given query expression. /// </summary> /// <param name="element">The element that contains the expression.</param> /// <param name="queryExpression">The query expression.</param> private void CheckQueryExpression(Element element, QueryExpression queryExpression) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(queryExpression, "queryExpression"); QueryClause previousClause = null; bool clauseOnSameLine = false; bool clauseOnSeparateLine = false; this.ProcessQueryClauses( element, queryExpression, queryExpression, ref previousClause, ref clauseOnSameLine, ref clauseOnSeparateLine); }
private void AddNewIdentifier(ParameterDefinition parameter) { VariableReference previousIdentifier = this.currentIdentifier; this.currentIdentifier = CreateNewIdentifier(parameter.Name, parameter.ParameterType); QueryClause previousClause = clauses[clauses.Count - 1]; if (previousClause.CodeNodeType != CodeNodeType.SelectClause && previousClause.CodeNodeType != CodeNodeType.GroupClause) { if (previousIdentifier == null) { throw new NullReferenceException("previousIdentifier"); } clauses.Add(new SelectClause(new VariableReferenceExpression(previousIdentifier, null), null)); } clauses.Add(new IntoClause(new VariableReferenceExpression(this.currentIdentifier, null), null)); }
public void OrderByBinder_BindsComputedPropertyInDollarOrderBy_FromDollarCompute() { // Arrange QueryClause clause = CreateQueryClause("$orderby=Total&$compute=Price mul Qty as Total", _model, typeof(ComputeCustomer)); ODataQuerySettings querySettings = new ODataQuerySettings(); IOrderByBinder binder = new OrderByBinder(); QueryBinderContext context = new QueryBinderContext(_model, querySettings, typeof(ComputeCustomer)); if (clause.Compute != null) { context.AddComputedProperties(clause.Compute.ComputedItems); } // Act OrderByBinderResult orderByResult = binder.BindOrderBy(clause.OrderBy, context); // Assert Assert.Null(orderByResult.ThenBy); Assert.Equal(OrderByDirection.Ascending, orderByResult.Direction); string resultExpression = ExpressionStringBuilder.ToString(orderByResult.OrderByExpression); Assert.Equal("$it => ($it.Price * Convert($it.Qty))", resultExpression); IEnumerable <ComputeCustomer> customers = new[] { new ComputeCustomer { Id = 1, Qty = 3, Price = 5.99 }, new ComputeCustomer { Id = 2, Qty = 5, Price = 2.99 }, new ComputeCustomer { Id = 3, Qty = 2, Price = 18.01 }, new ComputeCustomer { Id = 4, Qty = 4, Price = 9.99 }, }; var orderedResult = OrderByBinderTests.InvokeOrderBy(customers, orderByResult.OrderByExpression, orderByResult.Direction, false); Assert.True(new [] { 2, 1, 3, 4 }.SequenceEqual(orderedResult.Select(a => a.Id))); // ordered id }
/// <summary> /// Visits the query clause. /// </summary> /// <param name="clause">The clause.</param> /// <param name="parentClause">The parent clause.</param> /// <param name="parentExpression">The parent expression.</param> /// <param name="parentStatement">The parent statement.</param> /// <param name="parentElement">The parent element.</param> /// <param name="context">The context.</param> public virtual void VisitQueryClause(QueryClause clause, QueryClause parentClause, Expression parentExpression, Statement parentStatement, CsElement parentElement, object context) { }
void FixClauseIndentation(QueryClause clause, AstNode keyword) { var parentExpression = clause.GetParent<QueryExpression>(); bool isFirstClause = parentExpression.Clauses.First() == clause; if (!isFirstClause) { PlaceOnNewLine(policy.NewLineBeforeNewQueryClause, keyword); } int extraSpaces = options.IndentSize; curIndent.ExtraSpaces += extraSpaces; foreach (var child in clause.Children) { var expression = child as Expression; if (expression != null) { FixIndentation(child); child.AcceptVisitor(this); } var tokenNode = child as CSharpTokenNode; if (tokenNode != null) { if (tokenNode.GetNextSibling(NoWhitespacePredicate).StartLocation.Line != tokenNode.EndLocation.Line) { ForceSpacesAfter(tokenNode, false); } } } curIndent.ExtraSpaces -= extraSpaces; }
/// <summary> /// Analyzes the given query clauses. /// </summary> /// <param name="element">The element containing the clauses.</param> /// <param name="expression">The expression containing the clauses.</param> /// <param name="clauses">The list of clauses to analyze.</param> /// <param name="previousClause">The previous clause in the expression, if any.</param> /// <param name="clauseOnSameLine">Indicates whether any clause has been seen previously which /// starts on the same line as the clause before it.</param> /// <param name="clauseOnSeparateLine">Indicates whether any clause has been seen previously which /// starts on the line after the clause before it.</param> /// <returns>Returns true to continue checking the query clause, or false to quit.</returns> private bool ProcessQueryClauses( CsElement element, QueryExpression expression, ICollection<QueryClause> clauses, ref QueryClause previousClause, ref bool clauseOnSameLine, ref bool clauseOnSeparateLine) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(expression, "expression"); Param.AssertNotNull(clauses, "clauses"); Param.Ignore(previousClause); Param.Ignore(clauseOnSameLine); Param.Ignore(clauseOnSeparateLine); foreach (QueryClause clause in clauses) { if (previousClause != null) { // Figure out the line number that the previous clause ends on. For most // clauses, this is simply the end point of the clause location property, // but for continuation clauses we want to use the location of the 'into' variable, // which conceptually represents the end of the continuation line. int previousClauseEndLineNumber = previousClause.Location.EndPoint.LineNumber; if (previousClause.QueryClauseType == QueryClauseType.Continuation) { previousClauseEndLineNumber = ((QueryContinuationClause)previousClause).Variable.Location.LineNumber; } // Ensure that the clause either starts on the same line as the expression, or // on the very next line. if (clause.LineNumber == previousClauseEndLineNumber) { // This is only ok if the previous clause does not span multiple lines. if (previousClause.Location.LineSpan > 1) { this.AddViolation(element, clause.LineNumber, Rules.QueryClauseMustBeginOnNewLineWhenPreviousClauseSpansMultipleLines); return false; } // The rest of the checks are only applied when the clause is not a query continuation clause. A continuation // clause is allowed to begin at the end of the previous clause, on the same line. if (clause.QueryClauseType != QueryClauseType.Continuation) { // The clause starts on the same line as the ending of the previous clause. // This is ok as long as we have not previously seen a clause which starts // on its own line. The one exception is that query continuation clauses // are allowed to be inserted at the end of the previous claus. if (clauseOnSeparateLine) { this.AddViolation(element, clause.LineNumber, Rules.QueryClausesMustBeOnSeparateLinesOrAllOnOneLine); return false; } // If the clause spans multiple lines, it must begin on its own line. The exception is query continuation // clauses, which are allowed to begin at the end of the previous claus. if (clause.Location.LineSpan > 1) { this.AddViolation(element, clause.LineNumber, Rules.QueryClausesSpanningMultipleLinesMustBeginOnOwnLine); return false; } // Indicate that we have seen a clause which starts on the same line as the // previous clause. clauseOnSameLine = true; } } else if (clause.LineNumber == previousClauseEndLineNumber + 1) { // The clause starts on the line just after the previous clause. // This is fine unless we have previously seen two clauses on the same line. if (clauseOnSameLine) { this.AddViolation(element, clause.LineNumber, Rules.QueryClausesMustBeOnSeparateLinesOrAllOnOneLine); return false; } // Indicate that we have seen a clause which begins on the line after // the previous clause. clauseOnSeparateLine = true; } else if (clause.LineNumber > previousClauseEndLineNumber + 1) { // The clause does not start on the line after the previous clause. this.AddViolation(element, clause.LineNumber, Rules.QueryClauseMustFollowPreviousClause); return false; } } previousClause = clause; if (clause.QueryClauseType == QueryClauseType.Continuation) { QueryContinuationClause continuationClause = (QueryContinuationClause)clause; if (!this.ProcessQueryClauses( element, expression, continuationClause.ChildClauses, ref previousClause, ref clauseOnSameLine, ref clauseOnSeparateLine)) { return false; } } } return true; }
private bool VisitQueryClause(QueryClause clause, QueryClause parentClause, Expression parentExpression, Statement parentStatement, CsElement parentElement, object context) { this.analyzerRegistry.RuleAnalyzers.ForEach(analyzer => analyzer.VisitQueryClause(clause, parentClause, parentExpression, parentStatement, parentElement, context)); return true; }