Skip to content

Commit

Permalink
Add MergeAll and UpdateAll methods (surrealdb#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
Odonno authored Nov 30, 2023
1 parent e4c0f47 commit 8501a92
Show file tree
Hide file tree
Showing 8 changed files with 383 additions and 3 deletions.
111 changes: 111 additions & 0 deletions SurrealDb.Net.Tests/MergeAllTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System.Text;

namespace SurrealDb.Net.Tests;

public class MergeAllTests
{
[Theory]
[InlineData("http://localhost:8000")]
[InlineData("ws://localhost:8000/rpc")]
public async Task ShouldMergeAllRecords(string url)
{
IEnumerable<Post>? list = null;
IEnumerable<Post>? results = null;

Func<Task> func = async () =>
{
await using var surrealDbClientGenerator = new SurrealDbClientGenerator();
var dbInfo = surrealDbClientGenerator.GenerateDatabaseInfo();

string filePath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Schemas/post.surql"
);
string fileContent = File.ReadAllText(filePath, Encoding.UTF8);

string query = fileContent;

using var client = surrealDbClientGenerator.Create(url);
await client.SignIn(new RootAuth { Username = "root", Password = "root" });
await client.Use(dbInfo.Namespace, dbInfo.Database);
await client.Query(query);

var merge = new PostMergeData { Content = "[Edit] Oops" };

list = await client.Select<Post>("post");

results = await client.MergeAll<PostMergeData, Post>("post", merge);
};

await func.Should().NotThrowAsync();

list.Should().NotBeNull().And.HaveCount(2);

var expected = list!.Select(
item =>
new Post
{
Id = item.Id,
Title = item.Title,
Content = "[Edit] Oops",
CreatedAt = item.CreatedAt,
Status = item.Status,
}
);

results.Should().BeEquivalentTo(expected);
}

[Theory]
[InlineData("http://localhost:8000")]
[InlineData("ws://localhost:8000/rpc")]
public async Task ShouldMergeAllRecordsUsingDictionary(string url)
{
IEnumerable<Post>? list = null;
IEnumerable<Post>? results = null;

Func<Task> func = async () =>
{
await using var surrealDbClientGenerator = new SurrealDbClientGenerator();
var dbInfo = surrealDbClientGenerator.GenerateDatabaseInfo();

string filePath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Schemas/post.surql"
);
string fileContent = File.ReadAllText(filePath, Encoding.UTF8);

string query = fileContent;

using var client = surrealDbClientGenerator.Create(url);
await client.SignIn(new RootAuth { Username = "root", Password = "root" });
await client.Use(dbInfo.Namespace, dbInfo.Database);
await client.Query(query);

var thing = new Thing("post", "first");
var data = new Dictionary<string, object> { { "content", "[Edit] Oops" } };

list = await client.Select<Post>("post");

results = await client.MergeAll<Post>("post", data);
};

await func.Should().NotThrowAsync();

list.Should().NotBeNull().And.HaveCount(2);

var expected = list!.Select(
item =>
new Post
{
Id = item.Id,
Title = item.Title,
Content = "[Edit] Oops",
CreatedAt = item.CreatedAt,
Status = item.Status,
}
);

results.Should().BeEquivalentTo(expected);
}
}
11 changes: 8 additions & 3 deletions SurrealDb.Net.Tests/MergeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

namespace SurrealDb.Net.Tests;

public class PostMerge : SurrealDbRecord
public class PostMergeData
{
public string Content { get; set; } = string.Empty;
}

public class PostMergeRecord : SurrealDbRecord
{
public string Content { get; set; } = string.Empty;
}
Expand Down Expand Up @@ -35,13 +40,13 @@ public async Task ShouldMergeExistingPost(string url)
await client.Use(dbInfo.Namespace, dbInfo.Database);
await client.Query(query);

var merge = new PostMerge
var merge = new PostMergeRecord
{
Id = new Thing("post", "first"),
Content = "[Edit] This is my first article"
};

result = await client.Merge<PostMerge, Post>(merge);
result = await client.Merge<PostMergeRecord, Post>(merge);

list = await client.Select<Post>("post");
};
Expand Down
68 changes: 68 additions & 0 deletions SurrealDb.Net.Tests/UpdateAllTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System.Text;

namespace SurrealDb.Net.Tests;

public class UpdateAllTests
{
[Theory]
[InlineData("http://localhost:8000")]
[InlineData("ws://localhost:8000/rpc")]
public async Task ShouldUpdateAllRecords(string url)
{
IEnumerable<Post>? list = null;
IEnumerable<Post>? results = null;

var now = DateTime.UtcNow;

Func<Task> func = async () =>
{
await using var surrealDbClientGenerator = new SurrealDbClientGenerator();
var dbInfo = surrealDbClientGenerator.GenerateDatabaseInfo();

string filePath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Schemas/post.surql"
);
string fileContent = File.ReadAllText(filePath, Encoding.UTF8);

string query = fileContent;

using var client = surrealDbClientGenerator.Create(url);
await client.SignIn(new RootAuth { Username = "root", Password = "root" });
await client.Use(dbInfo.Namespace, dbInfo.Database);
await client.Query(query);

var postUpdate = new Post
{
Title = "# Title",
Content = "# Content",
CreatedAt = now,
Status = "PUBLISHED"
};

list = await client.Select<Post>("post");

results = await client.UpdateAll("post", postUpdate);
};

await func.Should().NotThrowAsync();

list.Should().NotBeNull().And.HaveCount(2);

results.Should().NotBeNull();

var expected = list!.Select(
item =>
new Post
{
Id = item.Id,
Title = "# Title",
Content = "# Content",
CreatedAt = now,
Status = "PUBLISHED",
}
);

results.Should().BeEquivalentTo(expected);
}
}
62 changes: 62 additions & 0 deletions SurrealDb.Net/Internals/SurrealDbEngine.Http.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,47 @@ CancellationToken cancellationToken
return okResult.DeserializeEnumerable<T>().First();
}

public async Task<IEnumerable<TOutput>> MergeAll<TMerge, TOutput>(
string table,
TMerge data,
CancellationToken cancellationToken
)
where TMerge : class
{
using var wrapper = CreateHttpClientWrapper();
using var body = CreateBodyContent(data);

using var response = await wrapper.Instance
.PatchAsync($"/key/{table}", body, cancellationToken)
.ConfigureAwait(false);

var dbResponse = await DeserializeDbResponseAsync(response, cancellationToken)
.ConfigureAwait(false);

var okResult = EnsuresFirstResultOk(dbResponse);
return okResult.DeserializeEnumerable<TOutput>();
}

public async Task<IEnumerable<T>> MergeAll<T>(
string table,
Dictionary<string, object> data,
CancellationToken cancellationToken
)
{
using var wrapper = CreateHttpClientWrapper();
using var body = CreateBodyContent(data);

using var response = await wrapper.Instance
.PatchAsync($"/key/{table}", body, cancellationToken)
.ConfigureAwait(false);

var dbResponse = await DeserializeDbResponseAsync(response, cancellationToken)
.ConfigureAwait(false);

var okResult = EnsuresFirstResultOk(dbResponse);
return okResult.DeserializeEnumerable<T>();
}

public async Task<SurrealDbResponse> Query(
string query,
IReadOnlyDictionary<string, object> parameters,
Expand Down Expand Up @@ -445,6 +486,27 @@ public Task Unset(string key, CancellationToken _)
return Task.CompletedTask;
}

public async Task<IEnumerable<T>> UpdateAll<T>(
string table,
T data,
CancellationToken cancellationToken
)
where T : class
{
using var wrapper = CreateHttpClientWrapper();
using var body = CreateBodyContent(data);

using var response = await wrapper.Instance
.PutAsync($"/key/{table}", body, cancellationToken)
.ConfigureAwait(false);

var dbResponse = await DeserializeDbResponseAsync(response, cancellationToken)
.ConfigureAwait(false);

var okResult = EnsuresFirstResultOk(dbResponse);
return okResult.DeserializeEnumerable<T>();
}

public async Task<T> Upsert<T>(T data, CancellationToken cancellationToken)
where T : Record
{
Expand Down
13 changes: 13 additions & 0 deletions SurrealDb.Net/Internals/SurrealDbEngine.Interface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ Task<T> Merge<T>(
Dictionary<string, object> data,
CancellationToken cancellationToken
);
Task<IEnumerable<TOutput>> MergeAll<TMerge, TOutput>(
string table,
TMerge data,
CancellationToken cancellationToken
)
where TMerge : class;
Task<IEnumerable<T>> MergeAll<T>(
string table,
Dictionary<string, object> data,
CancellationToken cancellationToken
);
Task<SurrealDbResponse> Query(
string query,
IReadOnlyDictionary<string, object> parameters,
Expand All @@ -60,6 +71,8 @@ Task<Jwt> SignUp<T>(T scopeAuth, CancellationToken cancellationToken)
where T : ScopeAuth;
SurrealDbLiveQueryChannel SubscribeToLiveQuery(Guid id);
Task Unset(string key, CancellationToken cancellationToken);
Task<IEnumerable<T>> UpdateAll<T>(string table, T data, CancellationToken cancellationToken)
where T : class;
Task<T> Upsert<T>(T data, CancellationToken cancellationToken)
where T : Record;
Task Use(string ns, string db, CancellationToken cancellationToken);
Expand Down
35 changes: 35 additions & 0 deletions SurrealDb.Net/Internals/SurrealDbEngine.Ws.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,29 @@ CancellationToken cancellationToken
return dbResponse.GetValue<T>()!;
}

public async Task<IEnumerable<TOutput>> MergeAll<TMerge, TOutput>(
string table,
TMerge data,
CancellationToken cancellationToken
)
where TMerge : class
{
var dbResponse = await SendRequest("merge", new() { table, data }, cancellationToken)
.ConfigureAwait(false);
return dbResponse.DeserializeEnumerable<TOutput>();
}

public async Task<IEnumerable<T>> MergeAll<T>(
string table,
Dictionary<string, object> data,
CancellationToken cancellationToken
)
{
var dbResponse = await SendRequest("merge", new() { table, data }, cancellationToken)
.ConfigureAwait(false);
return dbResponse.DeserializeEnumerable<T>();
}

public async Task<SurrealDbResponse> Query(
string query,
IReadOnlyDictionary<string, object> parameters,
Expand Down Expand Up @@ -523,6 +546,18 @@ public async Task Unset(string key, CancellationToken cancellationToken)
await SendRequest("unset", new() { key }, cancellationToken).ConfigureAwait(false);
}

public async Task<IEnumerable<T>> UpdateAll<T>(
string table,
T data,
CancellationToken cancellationToken
)
where T : class
{
var dbResponse = await SendRequest("update", new() { table, data }, cancellationToken)
.ConfigureAwait(false);
return dbResponse.DeserializeEnumerable<T>();
}

public async Task<T> Upsert<T>(T data, CancellationToken cancellationToken)
where T : Record
{
Expand Down
Loading

0 comments on commit 8501a92

Please sign in to comment.