Skip to content

Commit e5158ea

Browse files
committed
Fixed RemoveById with secondary indexes.
1 parent 0cd07c7 commit e5158ea

File tree

2 files changed

+52
-31
lines changed

2 files changed

+52
-31
lines changed

BTDB/ODBLayer/RelationDBManipulator.cs

+14-10
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ void FreeContentInUpdate(in ReadOnlySpan<byte> oldValueBytes, in ReadOnlySpan<by
519519
public unsafe bool RemoveById(scoped in ReadOnlySpan<byte> keyBytes, bool throwWhenNotFound)
520520
{
521521
using var cursor = _kvtr.CreateCursor();
522+
using var tempCursor = _kvtr.CreateCursor();
522523
Span<byte> keyBufferScoped = stackalloc byte[1024];
523524
Span<byte> keyBuffer =
524525
new Span<byte>(Unsafe.AsPointer(ref keyBufferScoped.GetPinnableReference()), keyBytes.Length);
@@ -571,7 +572,7 @@ public unsafe bool RemoveById(scoped in ReadOnlySpan<byte> keyBytes, bool throwW
571572

572573
if (_hasSecondaryIndexes)
573574
{
574-
RemoveSecondaryIndexes(cursor, fullKeyBytes, valueSpan);
575+
RemoveSecondaryIndexes(tempCursor, fullKeyBytes, valueSpan);
575576
}
576577

577578
_relationInfo.FreeContent(_transaction, valueSpan);
@@ -583,6 +584,7 @@ public unsafe bool RemoveById(scoped in ReadOnlySpan<byte> keyBytes, bool throwW
583584
public bool RemoveByIdWithFullKey(in ReadOnlySpan<byte> keyBytes, bool throwWhenNotFound)
584585
{
585586
using var cursor = _kvtr.CreateCursor();
587+
using var tempCursor = _kvtr.CreateCursor();
586588
Span<byte> valueBuffer = stackalloc byte[512];
587589

588590
var beforeRemove = _relationInfo.BeforeRemove;
@@ -612,7 +614,7 @@ public bool RemoveByIdWithFullKey(in ReadOnlySpan<byte> keyBytes, bool throwWhen
612614
cursor.EraseCurrent();
613615
if (_hasSecondaryIndexes)
614616
{
615-
RemoveSecondaryIndexes(cursor, keyBytes, value);
617+
RemoveSecondaryIndexes(tempCursor, keyBytes, value);
616618
}
617619

618620
_relationInfo.FreeContent(_transaction, value);
@@ -626,6 +628,7 @@ public unsafe bool ShallowRemoveById(in ReadOnlySpan<byte> keyBytes, bool throwW
626628
var beforeRemove = _relationInfo.BeforeRemove;
627629
ReadOnlySpan<byte> fullKeyBytes = keyBytes;
628630
using var cursor = _kvtr.CreateCursor();
631+
using var tempCursor = _kvtr.CreateCursor();
629632
Span<byte> keyBufferScoped = stackalloc byte[1024];
630633
Span<byte> keyBuffer =
631634
new Span<byte>(Unsafe.AsPointer(ref keyBufferScoped.GetPinnableReference()), keyBytes.Length);
@@ -675,7 +678,7 @@ public unsafe bool ShallowRemoveById(in ReadOnlySpan<byte> keyBytes, bool throwW
675678
var value = cursor.GetValueSpan(ref valueBuffer, true);
676679

677680
cursor.EraseCurrent();
678-
RemoveSecondaryIndexes(cursor, fullKeyBytes, value);
681+
RemoveSecondaryIndexes(tempCursor, fullKeyBytes, value);
679682
}
680683
else
681684
{
@@ -714,12 +717,12 @@ public int RemoveByPrimaryKeyPrefix(in ReadOnlySpan<byte> keyBytesPrefix)
714717

715718
if (_hasSecondaryIndexes || needImplementFreeContent)
716719
{
717-
var valueBytes = ((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor.GetValueSpan(ref buf, true);
720+
var valueBytes = ((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor!.GetValueSpan(ref buf, true);
718721

719722
if (_hasSecondaryIndexes)
720723
{
721724
RemoveSecondaryIndexes(tempCursor,
722-
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor.GetKeySpan(ref keyBuffer, true),
725+
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor!.GetKeySpan(ref keyBuffer, true),
723726
valueBytes);
724727
}
725728

@@ -729,7 +732,7 @@ public int RemoveByPrimaryKeyPrefix(in ReadOnlySpan<byte> keyBytesPrefix)
729732

730733
if (beforeRemove != null)
731734
{
732-
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor.EraseCurrent();
735+
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor!.EraseCurrent();
733736
}
734737

735738
removed++;
@@ -768,20 +771,20 @@ public int RemoveByPrimaryKeyPrefixPartial(in ReadOnlySpan<byte> keyBytesPrefix,
768771

769772
if (_hasSecondaryIndexes || needImplementFreeContent)
770773
{
771-
var valueBytes = ((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor.GetValueSpan(ref buf, true);
774+
var valueBytes = ((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor!.GetValueSpan(ref buf, true);
772775

773776
if (_hasSecondaryIndexes)
774777
{
775778
using var tempCursor = _kvtr.CreateCursor();
776779
RemoveSecondaryIndexes(tempCursor,
777-
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor.GetKeySpan(ref keyBuffer), valueBytes);
780+
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor!.GetKeySpan(ref keyBuffer), valueBytes);
778781
}
779782

780783
if (needImplementFreeContent)
781784
_relationInfo.FreeContent(_transaction, valueBytes);
782785
}
783786

784-
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor.EraseCurrent();
787+
((RelationPrimaryKeyEnumerator<T>)enumerator).Cursor!.EraseCurrent();
785788
removed++;
786789
}
787790

@@ -957,6 +960,7 @@ public unsafe int RemoveByIdAdvancedParam(EnumerationOrder order,
957960
using var enumerator = new RelationAdvancedEnumerator<T>(this,
958961
order, startKeyProposition, prefixLen, startKeyBytes, endKeyProposition, endKeyBytes, 0).GetEnumerator();
959962
var count = 0;
963+
using var tempCursor = _kvtr.CreateCursor();
960964
var cursor = ((RelationAdvancedEnumerator<T>)enumerator).Cursor;
961965
Span<byte> keyBufferScoped = stackalloc byte[1024];
962966
Span<byte> valueBuffer = stackalloc byte[1024];
@@ -977,7 +981,7 @@ public unsafe int RemoveByIdAdvancedParam(EnumerationOrder order,
977981

978982
if (_hasSecondaryIndexes)
979983
{
980-
RemoveSecondaryIndexes(cursor, fullKeyBytes, valueSpan);
984+
RemoveSecondaryIndexes(tempCursor, fullKeyBytes, valueSpan);
981985
}
982986

983987
_relationInfo.FreeContent(_transaction, valueSpan);

BTDBTest/ObjectDbTableInKeyValueTest.cs

+38-21
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ public class Person
1919
{
2020
[PrimaryKey(1)] public uint TenantId { get; set; }
2121

22-
[PrimaryKey(2)]
23-
public string? Email { get; set; }
22+
[PrimaryKey(2)] public string? Email { get; set; }
2423

25-
[InKeyValue(3)]
26-
public DateTime LastLogin { get; set; }
24+
[InKeyValue(3)] public DateTime LastLogin { get; set; }
2725

2826
public string? Name { get; set; }
2927
}
3028

3129
public interface IPersonTable : IRelation<Person>
3230
{
33-
IEnumerable<Person> ScanById(Constraint<ulong> tenantId, Constraint<string> email, Constraint<DateTime> lastLogin);
31+
IEnumerable<Person> ScanById(Constraint<ulong> tenantId, Constraint<string> email,
32+
Constraint<DateTime> lastLogin);
33+
3434
bool UpdateById(uint tenantId, string email, DateTime lastLogin);
3535
bool UpdateById(uint tenantId, string email, DateTime lastLogin, string name);
3636
void Insert(Person person);
@@ -87,7 +87,7 @@ public void RemoveByIdWorks()
8787
using var tr = _db.StartTransaction();
8888
var t = tr.GetRelation<IPersonTable>();
8989
t.RemoveById(1, "[email protected]");
90-
Assert.Equal(3,t.Count);
90+
Assert.Equal(3, t.Count);
9191
}
9292

9393
[Fact]
@@ -97,7 +97,8 @@ public void FullCaseUpdateByIdWorks()
9797

9898
using var tr = _db.StartTransaction();
9999
var t = tr.GetRelation<IPersonTable>();
100-
Assert.False(t.UpdateById(1, "[email protected]", new DateTime(2023, 7, 30, 0, 0, 0, DateTimeKind.Utc), "does not matter"));
100+
Assert.False(t.UpdateById(1, "[email protected]", new DateTime(2023, 7, 30, 0, 0, 0, DateTimeKind.Utc),
101+
"does not matter"));
101102
Assert.True(t.UpdateById(1, "[email protected]", new DateTime(2023, 7, 30, 0, 0, 0, DateTimeKind.Utc), "OK"));
102103
Assert.Equal("A",
103104
string.Join("",
@@ -116,13 +117,16 @@ public void InsertAndUpdateWorks()
116117

117118
using var tr = _db.StartTransaction();
118119
var t = tr.GetRelation<IPersonTable>();
119-
t.Insert(new() { TenantId = 1, Email = "[email protected]", Name = "BB", LastLogin = new(2023, 7, 30, 0, 0, 0, DateTimeKind.Utc) });
120+
t.Insert(new()
121+
{ TenantId = 1, Email = "[email protected]", Name = "BB", LastLogin = new(2023, 7, 30, 0, 0, 0, DateTimeKind.Utc) });
120122
Assert.Equal("BB",
121123
t.ScanById(Constraint.Unsigned.Exact(1), Constraint.String.Exact("[email protected]"), Constraint<DateTime>.Any)
122124
.Single().Name);
123-
t.Update(new() { TenantId = 1, Email = "[email protected]", Name = "CC", LastLogin = new(2024, 1,1,0,0,0,DateTimeKind.Utc) });
125+
t.Update(new()
126+
{ TenantId = 1, Email = "[email protected]", Name = "CC", LastLogin = new(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc) });
124127
Assert.Equal("CC",
125-
t.ScanById(Constraint.Unsigned.Exact(1), Constraint.String.Exact("[email protected]"), Constraint.DateTime.Predicate(d=>d.Year==2024))
128+
t.ScanById(Constraint.Unsigned.Exact(1), Constraint.String.Exact("[email protected]"),
129+
Constraint.DateTime.Predicate(d => d.Year == 2024))
126130
.Single().Name);
127131
}
128132

@@ -161,8 +165,7 @@ public class DataV2
161165

162166
public string Name { get; set; }
163167

164-
[InKeyValue(2)]
165-
public int Age { get; set; }
168+
[InKeyValue(2)] public int Age { get; set; }
166169
}
167170

168171
[PersistedName("Data")]
@@ -177,8 +180,8 @@ public void PromotionValueToInKeyValueWorks()
177180
{
178181
using var tr = _db.StartTransaction();
179182
var t = tr.GetRelation<IDataV1Table>();
180-
t.Upsert(new (){ Id = 1, Name = "A", Age = 11});
181-
t.Upsert(new (){ Id = 2, Name = "B", Age = 22});
183+
t.Upsert(new() { Id = 1, Name = "A", Age = 11 });
184+
t.Upsert(new() { Id = 2, Name = "B", Age = 22 });
182185
tr.Commit();
183186
}
184187
ReopenDb();
@@ -206,17 +209,16 @@ public void PromotionValueToInKeyValueWorks()
206209

207210
public class ListData
208211
{
209-
[PrimaryKey(1)]
210-
public uint Id { get; set; }
211-
[PrimaryKey(2)]
212-
public uint QueueStamp { get; set; }
213-
[PrimaryKey(3, InKeyValue = true)]
214-
public bool IsProcessed { get; set; }
212+
[PrimaryKey(1)] public uint Id { get; set; }
213+
[PrimaryKey(2)] public uint QueueStamp { get; set; }
214+
[PrimaryKey(3, InKeyValue = true)] public bool IsProcessed { get; set; }
215+
[SecondaryKey("SomeKey")] public string? SomeKey { get; set; }
215216
}
216217

217218
public interface IListDataTable : IRelation<ListData>
218219
{
219220
IEnumerable<ListData> ListById(uint id, AdvancedEnumeratorParam<uint> queueStampParam);
221+
int RemoveById(uint id, AdvancedEnumeratorParam<uint> queueStampParam);
220222
}
221223

222224
[Fact]
@@ -226,7 +228,22 @@ public void ListingWithAdvancedEnumeratorParam()
226228

227229
using var tr = _db.StartTransaction();
228230
var t = tr.GetRelation<IListDataTable>();
229-
Assert.Equal(2, t.ListById(1, new(EnumerationOrder.Ascending, 2, KeyProposition.Excluded, uint.MaxValue, KeyProposition.Included)).Count());
231+
Assert.Equal(2,
232+
t.ListById(1,
233+
new(EnumerationOrder.Ascending, 2, KeyProposition.Excluded, uint.MaxValue, KeyProposition.Included))
234+
.Count());
235+
}
236+
237+
[Fact]
238+
public void RemoveByIdWithAdvancedEnumeratorParam()
239+
{
240+
FillListingData();
241+
242+
using var tr = _db.StartTransaction();
243+
var t = tr.GetRelation<IListDataTable>();
244+
Assert.Equal(2,
245+
t.RemoveById(1, new(EnumerationOrder.Ascending, 2, KeyProposition.Included, 3, KeyProposition.Included)));
246+
Assert.Equal(2, t.Count);
230247
}
231248

232249
void FillListingData()

0 commit comments

Comments
 (0)