Skip to content

Commit 7d1978d

Browse files
v3.4.0
v3.4.0
2 parents 9b55e16 + b63a8b8 commit 7d1978d

File tree

69 files changed

+540
-39353
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+540
-39353
lines changed

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# 3.4.0 (2023-06-21)
2+
3+
## Features
4+
5+
* **Database split**: Configurable field for document discrimination ([#150](https://github.com/matteobortolazzo/couchdb-net/issues/150))
6+
* **Find**: Added all options and responses ([#182](https://github.com/matteobortolazzo/couchdb-net/issues/182))
7+
* **Change feed**: Adds support for database split ([#187](https://github.com/matteobortolazzo/couchdb-net/issues/187))
8+
* **Replicas**: Adds `CreateTarget` option ([#189](https://github.com/matteobortolazzo/couchdb-net/issues/189))
9+
10+
## Bugs
11+
12+
* **Queries**: Fix when `In` is called inside `Any` ([#183](https://github.com/matteobortolazzo/couchdb-net/issues/183))
13+
* **Database split**: Fix `FirstOrDefault` without filter queries ([#185](https://github.com/matteobortolazzo/couchdb-net/issues/185))
14+
115
# 3.3.1 (2022-10-26)
216

317
## Bug Fixes

LATEST_CHANGE.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1-
## Bug Fixes
1+
# 3.4.0 (2023-06-21)
22

3-
* **Dependency Injection**: Fix dependency injection packages references ([#180](https://github.com/matteobortolazzo/couchdb-net/pull/180))
3+
## Features
4+
5+
* **Database split**: Configurable field for document discrimination ([#150](https://github.com/matteobortolazzo/couchdb-net/issues/150))
6+
* **Find**: Added all options and responses ([#182](https://github.com/matteobortolazzo/couchdb-net/issues/182))
7+
* **Change feed**: Adds support for database split ([#187](https://github.com/matteobortolazzo/couchdb-net/issues/187))
8+
* **Replicas**: Adds `CreateTarget` option ([#189](https://github.com/matteobortolazzo/couchdb-net/issues/189))
9+
10+
## Bugs
11+
12+
* **Queries**: Fix when `In` is called inside `Any` ([#183](https://github.com/matteobortolazzo/couchdb-net/issues/183))
13+
* **Database split**: Fix `FirstOrDefault` without filter queries ([#185](https://github.com/matteobortolazzo/couchdb-net/issues/185))

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,8 @@ public class MyDeathStarContext : CouchContext
536536
> When multiple `CouchDatabase` point to the same **database**, a `split_discriminator` field is added on document creation.
537537
>
538538
> When querying, a filter by `split_discriminator` is added automatically.
539+
>
540+
> The field name can be overriden with the `WithDatabaseSplitDiscriminator`.
539541

540542
If you are not using `CouchContext`, you can still use the database split feature:
541543
```csharp

src/CouchDB.Driver.DependencyInjection.Autofac/CouchDB.Driver.DependencyInjection.Autofac.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<PackageProjectUrl>https://github.com/matteobortolazzo/couchdb-net</PackageProjectUrl>
99
<RepositoryUrl>https://github.com/matteobortolazzo/couchdb-net</RepositoryUrl>
1010
<PackageTags>couchdb,driver,nosql,netstandard,pouchdb,xamarin</PackageTags>
11-
<PackageReleaseNotes></PackageReleaseNotes>
1211
<ApplicationIcon />
1312
<OutputType>Library</OutputType>
1413
<StartupObject />
@@ -31,7 +30,7 @@
3130

3231
<ItemGroup>
3332
<PackageReference Include="CouchDB.NET" Version="3.3.*" />
34-
<PackageReference Include="Autofac" Version="5.2.0" />
33+
<PackageReference Include="Autofac" Version="6.5.0" />
3534
</ItemGroup>
3635

3736
</Project>

src/CouchDB.Driver.DependencyInjection/CouchDB.Driver.DependencyInjection.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<PackageProjectUrl>https://github.com/matteobortolazzo/couchdb-net</PackageProjectUrl>
99
<RepositoryUrl>https://github.com/matteobortolazzo/couchdb-net</RepositoryUrl>
1010
<PackageTags>couchdb,driver,nosql,netstandard,pouchdb,xamarin</PackageTags>
11-
<PackageReleaseNotes></PackageReleaseNotes>
1211
<ApplicationIcon />
1312
<OutputType>Library</OutputType>
1413
<StartupObject />
@@ -31,7 +30,7 @@
3130

3231
<ItemGroup>
3332
<PackageReference Include="CouchDB.NET" Version="3.3.*" />
34-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.26" />
33+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
3534
</ItemGroup>
3635

3736
</Project>

src/CouchDB.Driver/CouchClient.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace CouchDB.Driver
2323
/// </summary>
2424
public partial class CouchClient : ICouchClient
2525
{
26+
public const string DefaultDatabaseSplitDiscriminator = "split_discriminator";
2627
private DateTime? _cookieCreationDate;
2728
private string? _cookieToken;
2829

@@ -91,7 +92,7 @@ private IFlurlClient GetConfiguredClient() =>
9192
{
9293
s.JsonSerializer = new NewtonsoftJsonSerializer(new JsonSerializerSettings
9394
{
94-
ContractResolver = new CouchContractResolver(_options.PropertiesCase),
95+
ContractResolver = new CouchContractResolver(_options.PropertiesCase, _options.DatabaseSplitDiscriminator),
9596
NullValueHandling = _options.NullValueHandling ?? NullValueHandling.Include
9697
});
9798
s.BeforeCallAsync = OnBeforeCallAsync;

src/CouchDB.Driver/CouchDB.Driver.csproj

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<PackageProjectUrl>https://github.com/matteobortolazzo/couchdb-net</PackageProjectUrl>
99
<RepositoryUrl>https://github.com/matteobortolazzo/couchdb-net</RepositoryUrl>
1010
<PackageTags>couchdb,driver,nosql,netstandard,pouchdb,xamarin</PackageTags>
11-
<PackageReleaseNotes></PackageReleaseNotes>
1211
<ApplicationIcon />
1312
<OutputType>Library</OutputType>
1413
<StartupObject />
@@ -30,8 +29,8 @@
3029
</PropertyGroup>
3130

3231
<ItemGroup>
33-
<PackageReference Include="Flurl.Http" Version="3.2.0" />
34-
<PackageReference Include="Humanizer.Core" Version="2.11.10" />
32+
<PackageReference Include="Flurl.Http" Version="3.2.4" />
33+
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
3534
</ItemGroup>
3635

3736
<ItemGroup>

src/CouchDB.Driver/CouchDatabase.cs

+73-9
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,7 @@ internal CouchDatabase(IFlurlClient flurlClient, CouchOptions options, QueryCont
8383
IFlurlRequest request = NewRequest()
8484
.AppendPathSegment(Uri.EscapeDataString(docId));
8585

86-
if (options.Conflicts)
87-
request = request.SetQueryParam("conflicts", "true");
88-
89-
if (options.Rev != null)
90-
request = request.SetQueryParam("rev", options.Rev);
91-
92-
IFlurlResponse? response = await request
86+
IFlurlResponse? response = await SetFindOptions(request, options)
9387
.AllowHttpStatus(HttpStatusCode.NotFound)
9488
.GetAsync(cancellationToken)
9589
.ConfigureAwait(false);
@@ -432,11 +426,19 @@ public async Task<ChangesFeedResponse<TSource>> GetChangesAsync(ChangesFeedOptio
432426
request = request.ApplyQueryParametersOptions(options);
433427
}
434428

435-
return filter == null
429+
ChangesFeedResponse<TSource>? response = filter == null
436430
? await request.GetJsonAsync<ChangesFeedResponse<TSource>>(cancellationToken)
437431
.ConfigureAwait(false)
438432
: await request.QueryWithFilterAsync<TSource>(_queryProvider, filter, cancellationToken)
439433
.ConfigureAwait(false);
434+
435+
if (string.IsNullOrWhiteSpace(_discriminator))
436+
{
437+
return response;
438+
}
439+
440+
response.Results = response.Results.Where(result => result.Document.SplitDiscriminator == _discriminator).ToArray();
441+
return response;
440442
}
441443

442444
/// <inheritdoc />
@@ -474,7 +476,11 @@ public async IAsyncEnumerable<ChangesFeedResponseResult<TSource>> GetContinuousC
474476
var endIndex = i < matches.Count - 1 ? matches[i + 1].Index : line.Length;
475477
var lineLength = endIndex - startIndex;
476478
var substring = line.Substring(startIndex, lineLength);
477-
yield return JsonConvert.DeserializeObject<ChangesFeedResponseResult<TSource>>(substring);
479+
ChangesFeedResponseResult<TSource>? result = JsonConvert.DeserializeObject<ChangesFeedResponseResult<TSource>>(substring);
480+
if (string.IsNullOrWhiteSpace(_discriminator) || result.Document.SplitDiscriminator == _discriminator)
481+
{
482+
yield return result;
483+
}
478484
}
479485
}
480486
}
@@ -738,6 +744,64 @@ internal IndexBuilder<TSource> NewIndexBuilder(
738744
return builder;
739745
}
740746

747+
private static IFlurlRequest SetFindOptions(IFlurlRequest request, FindOptions options)
748+
{
749+
if (options.Attachments)
750+
{
751+
request = request.SetQueryParam("attachments", "true");
752+
}
753+
if (options.AttachmentsEncodingInfo)
754+
{
755+
request = request.SetQueryParam("att_encoding_info", "true");
756+
}
757+
if (options.AttachmentsSince != null && options.AttachmentsSince.Any())
758+
{
759+
request = request.SetQueryParam("att_encoding_info", options.AttachmentsSince);
760+
}
761+
if (options.Conflicts)
762+
{
763+
request = request.SetQueryParam("conflicts", "true");
764+
}
765+
if (options.DeleteConflicts)
766+
{
767+
request = request.SetQueryParam("deleted_conflicts", "true");
768+
}
769+
if (options.DeleteConflicts)
770+
{
771+
request = request.SetQueryParam("deleted_conflicts", "true");
772+
}
773+
if (options.Latest)
774+
{
775+
request = request.SetQueryParam("latest", "true");
776+
}
777+
if (options.LocalSequence)
778+
{
779+
request = request.SetQueryParam("local_seq", "true");
780+
}
781+
if (options.Meta)
782+
{
783+
request = request.SetQueryParam("meta", "true");
784+
}
785+
if (options.OpenRevisions != null && options.OpenRevisions.Any())
786+
{
787+
request = request.SetQueryParam("open_revs", options.AttachmentsSince);
788+
}
789+
if (options.Revision != null)
790+
{
791+
request = request.SetQueryParam("rev", options.Revision);
792+
}
793+
if (options.Revisions)
794+
{
795+
request = request.SetQueryParam("revs", "true");
796+
}
797+
if (options.RevisionsInfo)
798+
{
799+
request = request.SetQueryParam("revs_info", "true");
800+
}
801+
802+
return request;
803+
}
804+
741805
#endregion
742806
}
743807
}

src/CouchDB.Driver/DatabaseApiMethodOptions/FindOptions.cs

+53-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,63 @@ namespace CouchDB.Driver.DatabaseApiMethodOptions
1111
public class FindOptions
1212
{
1313
/// <summary>
14-
/// Includes information about conflicts in document. Default is false
14+
/// Includes attachments bodies in response. Default is <c>False</c>
1515
/// </summary>
16-
public bool Conflicts { get; set; } = false;
16+
public bool Attachments { get; set; }
17+
18+
/// <summary>
19+
/// Includes encoding information in attachment stubs if the particular attachment is compressed. Default is <c>False</c>
20+
/// </summary>
21+
public bool AttachmentsEncodingInfo { get; set; }
22+
23+
/// <summary>
24+
/// Includes attachments only since specified revisions. Doesn’t includes attachments for specified revisions. Optional
25+
/// </summary>
26+
public IList<string>? AttachmentsSince { get; set; }
27+
28+
/// <summary>
29+
/// Includes information about conflicts in document. Default is <c>False</c>
30+
/// </summary>
31+
public bool Conflicts { get; set; }
1732

33+
/// <summary>
34+
/// Includes information about deleted conflicted revisions. Default is <c>False</c>
35+
/// </summary>
36+
public bool DeleteConflicts { get; set; }
37+
38+
/// <summary>
39+
/// Forces retrieving latest “leaf” revision, no matter what rev was requested. Default is <c>False</c>
40+
/// </summary>
41+
public bool Latest { get; set; }
42+
43+
/// <summary>
44+
/// Includes last update sequence for the document. Default is <<c>False</c>
45+
/// </summary>
46+
public bool LocalSequence { get; set; }
47+
48+
/// <summary>
49+
/// Acts same as specifying all <see cref="Conflicts"/>, <see cref="DeleteConflicts"/> and <see cref="RevisionsInfo"/> query parameters. Default is <c>False</c>
50+
/// </summary>
51+
public bool Meta { get; set; }
52+
53+
/// <summary>
54+
/// Retrieves documents of specified leaf revisions. Additionally, it accepts value as all to return all leaf revisions. Optional
55+
/// </summary>
56+
public IList<string>? OpenRevisions { get; set; }
57+
1858
/// <summary>
1959
/// Retrieves document of specified revision. Optional
2060
/// </summary>
21-
public string? Rev { get; set; }
61+
public string? Revision { get; set; }
62+
63+
/// <summary>
64+
/// Includes list of all known document revisions. Default is <c>False</c>
65+
/// </summary>
66+
public bool Revisions { get; set; }
67+
68+
/// <summary>
69+
/// Includes detailed information for all known document revisions. Default is <c>False</c>
70+
/// </summary>
71+
public bool RevisionsInfo { get; set; }
2272
}
2373
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.ComponentModel;
2-
using System.Reflection;
1+
using System.Reflection;
32
using CouchDB.Driver.Extensions;
43
using CouchDB.Driver.Options;
54
using Newtonsoft.Json;
@@ -10,26 +9,32 @@ namespace CouchDB.Driver.Helpers
109
public class CouchContractResolver : DefaultContractResolver
1110
{
1211
private readonly PropertyCaseType _propertyCaseType;
12+
private readonly string? _databaseSplitDiscriminator;
1313

14-
internal CouchContractResolver(PropertyCaseType propertyCaseType)
14+
internal CouchContractResolver(PropertyCaseType propertyCaseType, string? databaseSplitDiscriminator)
1515
{
1616
_propertyCaseType = propertyCaseType;
17+
_databaseSplitDiscriminator = databaseSplitDiscriminator;
1718
}
1819

1920
protected override JsonProperty? CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
2021
{
2122
Check.NotNull(member, nameof(member));
2223

2324
JsonProperty property = base.CreateProperty(member, memberSerialization);
24-
if (property != null && !property.Ignored)
25+
if (property is { Ignored: false })
2526
{
26-
var declaringNamespace = member.DeclaringType?.Namespace;
27-
if (declaringNamespace != null && !declaringNamespace.Contains("CouchDB.Driver"))
27+
if (member.DeclaringType!.Assembly != GetType().Assembly)
2828
{
2929
property.PropertyName = member.GetCouchPropertyName(_propertyCaseType);
3030
}
3131
}
32+
33+
if (property.PropertyName == CouchClient.DefaultDatabaseSplitDiscriminator && !string.IsNullOrWhiteSpace(_databaseSplitDiscriminator))
34+
{
35+
property.PropertyName = _databaseSplitDiscriminator;
36+
}
3237
return property;
3338
}
3439
}
35-
}
40+
}

src/CouchDB.Driver/Helpers/MethodCallExpressionBuilder.cs

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ internal static class MethodCallExpressionBuilder
1111
{
1212
#region Substitute
1313

14+
public static MethodCallExpression TrySubstituteWithOptimized(this MethodCallExpression node, string methodName, Func<MethodCallExpression, Expression> visitMethod)
15+
{
16+
if (node.Arguments.Count > 0 && node.Arguments[0] is MethodCallExpression methodCallExpression)
17+
{
18+
Expression? optimizedArgument = visitMethod(methodCallExpression);
19+
node = Expression.Call(typeof(Queryable), methodName,
20+
node.Method.GetGenericArguments(), optimizedArgument);
21+
}
22+
23+
return node;
24+
}
25+
1426
public static MethodCallExpression SubstituteWithQueryableCall(this MethodCallExpression node, string methodName)
1527
{
1628
Check.NotNull(node, nameof(node));

src/CouchDB.Driver/Options/CouchOptions.cs

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public abstract class CouchOptions
2727
internal bool PluralizeEntities { get; set; }
2828
internal DocumentCaseType DocumentsCaseType { get; set; }
2929
internal PropertyCaseType PropertiesCase { get; set; }
30+
31+
internal string? DatabaseSplitDiscriminator { get; set; }
3032
internal NullValueHandling? NullValueHandling { get; set; }
3133
internal bool LogOutOnDispose { get; set; }
3234

src/CouchDB.Driver/Options/CouchOptionsBuilder.cs

+11
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,17 @@ public virtual CouchOptionsBuilder SetPropertyCase(PropertyCaseType type)
193193
return this;
194194
}
195195

196+
/// <summary>
197+
/// Set the field to use to identify document types. Default: <c>split_discriminator</c>.
198+
/// </summary>
199+
/// <param name="databaseSplitDiscriminator">The document field to use as discriminator.</param>
200+
/// <returns>Return the current instance to chain calls.</returns>
201+
public virtual CouchOptionsBuilder WithDatabaseSplitDiscriminator(string databaseSplitDiscriminator)
202+
{
203+
Options.DatabaseSplitDiscriminator = databaseSplitDiscriminator;
204+
return this;
205+
}
206+
196207
/// <summary>
197208
/// Sets how to handle null values during serialization.
198209
/// </summary>

0 commit comments

Comments
 (0)