Skip to content

Commit

Permalink
Add support for GROUP BY queries (#74)
Browse files Browse the repository at this point in the history
* Fix #72
Retrieving ContinuationToken after a query with a GROUP BY is throwing an exception.

* Add missing keywords/function for aggregate queries

* Fix issue for queries with that respond with only 1 value (not object)

* Try to remove system properties only from JObject
  • Loading branch information
sachabruttin authored Jun 16, 2022
1 parent 2eb0970 commit 8c06eb5
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace CosmosDbExplorer.Core.Contracts.Services
public interface ICosmosDocumentService
{
Task<CosmosResult> DeleteDocumentsAsync(IEnumerable<ICosmosDocument> documents, CancellationToken cancellationToken);
Task<CosmosQueryResult<IReadOnlyCollection<JObject>>> ExecuteQueryAsync(ICosmosQuery query, CancellationToken cancellationToken);
Task<CosmosQueryResult<IReadOnlyCollection<JToken>>> ExecuteQueryAsync(ICosmosQuery query, CancellationToken cancellationToken);
Task<CosmosQueryResult<JObject>> GetDocumentAsync(ICosmosDocument document, IDocumentRequestOptions options, CancellationToken cancellation);
Task<CosmosQueryResult<IReadOnlyCollection<ICosmosDocument>>> GetDocumentsAsync(string? filter, int? maxItemsCount, string? continuationToken, CancellationToken cancellationToken);
Task<CosmosQueryResult<JObject>> SaveDocumentAsync(string content, IDocumentRequestOptions options, CancellationToken cancellation);
Expand Down
2 changes: 1 addition & 1 deletion src/CosmosDbExplorer.Core/CosmosDbExplorer.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.26.1" />
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.28.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
23 changes: 23 additions & 0 deletions src/CosmosDbExplorer.Core/Helpers/CosmosExceptionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
using System.Linq;
using System.Text.RegularExpressions;

using CosmosDbExplorer.Core.Models;

using Microsoft.Azure.Cosmos;

using Newtonsoft.Json;

namespace CosmosDbExplorer.Core.Helpers
{
public static class CosmosExceptionHelper
Expand All @@ -12,6 +16,11 @@ public static string GetMessage(this CosmosException exception)
{
try
{
if (TryGetQuerySyntaxException(exception, out var querySyntaxException))
{
return querySyntaxException ?? string.Empty;
}

if (TryGetErrors(exception, out var errors))
{
return errors ?? string.Empty;
Expand Down Expand Up @@ -61,6 +70,20 @@ private static bool TryGetErrors(CosmosException exception, out string? message)
}
}

private static bool TryGetQuerySyntaxException(CosmosException exception, out string? message)
{
var obj = JsonConvert.DeserializeObject<CosmosQuerySyntaxException>(exception.ResponseBody);

if (obj is not null && obj.Errors.Any())
{
message = string.Join(Environment.NewLine, obj.Errors.Select(error => $"{error.Message} ({error.Location?.Start}, {error.Location?.End})"));
return true;
}

message = null;
return false;
}

private static bool TryGetUpdatingOfferException(CosmosException exception, out string? message)
{
try
Expand Down
24 changes: 24 additions & 0 deletions src/CosmosDbExplorer.Core/Helpers/FeedResponseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Azure.Cosmos;

namespace CosmosDbExplorer.Core.Helpers
{
public static class FeedResponseExtensions
{
public static string? GetContinuationTokenSafely<T>(this FeedResponse<T> feedResponse)
{
try
{
return feedResponse.ContinuationToken;
}
catch (ArgumentException ex) when (ex.Message == "Continuation token is not supported for queries with GROUP BY. Do not use FeedResponse.ResponseContinuation or remove the GROUP BY from the query.")
{
// Silently catch exception
return null;
}
}
}
}
38 changes: 38 additions & 0 deletions src/CosmosDbExplorer.Core/Models/CosmosQuerySyntaxException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Text;

using Newtonsoft.Json;

namespace CosmosDbExplorer.Core.Models
{
public class CosmosQuerySyntaxException
{
[JsonProperty("errors")]
public List<Error>? Errors { get; set; }
}

public partial class Error
{
[JsonProperty("severity")]
public string? Severity { get; set; }

[JsonProperty("location")]
public Location? Location { get; set; }

[JsonProperty("code")]
public string? Code { get; set; }

[JsonProperty("message")]
public string? Message { get; set; }
}

public partial class Location
{
[JsonProperty("start")]
public long? Start { get; set; }

[JsonProperty("end")]
public long? End { get; set; }
}
}
8 changes: 4 additions & 4 deletions src/CosmosDbExplorer.Core/Services/CosmosDocumentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ public async Task<int> ImportDocumentsAsync(string content, CancellationToken ca
return tasks.Where(t => t.IsCompletedSuccessfully).Count();
}

public async Task<CosmosQueryResult<IReadOnlyCollection<JObject>>> ExecuteQueryAsync(ICosmosQuery query, CancellationToken cancellationToken)
public async Task<CosmosQueryResult<IReadOnlyCollection<JToken>>> ExecuteQueryAsync(ICosmosQuery query, CancellationToken cancellationToken)
{
var result = new CosmosQueryResult<IReadOnlyCollection<JObject>>();
var result = new CosmosQueryResult<IReadOnlyCollection<JToken>>();

var options = new QueryRequestOptions
{
Expand All @@ -222,15 +222,15 @@ public async Task<CosmosQueryResult<IReadOnlyCollection<JObject>>> ExecuteQueryA

try
{
using (var resultSet = _container.GetItemQueryIterator<JObject>(
using (var resultSet = _container.GetItemQueryIterator<JToken>(
queryText: query.QueryText,
continuationToken: query.ContinuationToken,
requestOptions: options))
{
var response = await resultSet.ReadNextAsync(cancellationToken);

result.RequestCharge = response.RequestCharge;
result.ContinuationToken = response.ContinuationToken;
result.ContinuationToken = response.GetContinuationTokenSafely();
result.Items = response.Resource.ToArray();
result.Headers = response.Headers.ToDictionary();
//result.Diagnostics = response.Diagnostics.ToString;
Expand Down
8 changes: 7 additions & 1 deletion src/CosmosDbExplorer/AvalonEdit/DocumentDbSql.xshd
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
<Word>TOP</Word>
<Word>VALUE</Word>
<Word>WHERE</Word>
<Word>GROUP BY</Word>
</Keywords>
<Keywords color="Function">
<!--https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-sql-query-reference#bk_mathematical_functions-->
Expand All @@ -114,14 +115,18 @@
<Word>ASIN</Word>
<Word>ATAN</Word>
<Word>ATN2</Word>
<Word>AVG</Word>
<Word>CEILING</Word>
<Word>COS</Word>
<Word>COT</Word>
<Word>COUNT</Word>
<Word>DEGREES</Word>
<Word>EXP</Word>
<Word>FLOOR</Word>
<Word>LOG</Word>
<Word>LOG10</Word>
<Word>LOG10</Word>
<Word>MAX</Word>
<Word>MIN</Word>
<Word>PI</Word>
<Word>POWER</Word>
<Word>RADIANS</Word>
Expand All @@ -130,6 +135,7 @@
<Word>SQRT</Word>
<Word>SQUARE</Word>
<Word>SIGN</Word>
<Word>SUM</Word>
<Word>TAN</Word>
<Word>TRUNC</Word>
<!--https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-sql-query-reference#bk_type_checking_functions-->
Expand Down
6 changes: 3 additions & 3 deletions src/CosmosDbExplorer/CosmosDbExplorer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@
<EmbeddedResource Include="AvalonEdit\JSON.xshd" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autoupdater.NET.Official" Version="1.7.0" />
<PackageReference Include="Autoupdater.NET.Official" Version="1.7.3" />
<PackageReference Include="AvalonEdit" Version="6.1.3.50" />
<PackageReference Include="Dirkster.AvalonDock" Version="4.70.1" />
<PackageReference Include="Dirkster.AvalonDock.Themes.VS2013" Version="4.70.1" />
<PackageReference Include="Fluent.Ribbon" Version="9.0.4" />
<PackageReference Include="FluentValidation" Version="10.4.0" />
<PackageReference Include="Fody" Version="6.6.0">
<PackageReference Include="Fody" Version="6.6.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="gong-wpf-dragdrop" Version="3.1.1" />
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.1.2" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.1" />
<PackageReference Include="Validar.Fody" Version="1.9.0" />
</ItemGroup>
<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/CosmosDbExplorer/ViewModels/JsonEditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private static string RemoveCosmosSystemProperties(JArray content)
{
var innerContent = JArray.FromObject(content);

foreach (var obj in innerContent.Values<JObject>())
foreach (var obj in innerContent.Children<JObject>())
{
if (obj != null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/CosmosDbExplorer/ViewModels/QueryEditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace CosmosDbExplorer.ViewModels
public class QueryEditorViewModel : PaneWithZoomViewModel<ContainerNodeViewModel>
, IHaveSystemProperties
{
private CosmosQueryResult<IReadOnlyCollection<JObject>>? _queryResult;
private CosmosQueryResult<IReadOnlyCollection<JToken>>? _queryResult;
private readonly StatusBarItem _requestChargeStatusBarItem;
private readonly StatusBarItem _queryInformationStatusBarItem;
private readonly StatusBarItem _progessBarStatusBarItem;
Expand Down

0 comments on commit 8c06eb5

Please sign in to comment.