Skip to content

Commit d4115b6

Browse files
committed
Implemented move_next_multiple
1 parent 4ea188a commit d4115b6

File tree

8 files changed

+143
-21
lines changed

8 files changed

+143
-21
lines changed

src/LightningDB.Tests/CursorTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,5 +277,26 @@ public void ShouldGetMultiple()
277277
Assert.IsTrue(result);
278278
CollectionAssert.AreEqual(values, resultArray);
279279
}
280+
281+
[Test]
282+
public void ShouldMoveNextMultiple()
283+
{
284+
//arrange
285+
_db = _txn.OpenDatabase(options: new DatabaseOptions { Flags = DatabaseOpenFlags.DuplicatesFixed });
286+
const string key = "TestKey";
287+
288+
var values = new[] { 1, 2, 3, 4, 5 };
289+
using (var cur = _txn.CreateCursor(_db))
290+
cur.PutMultiple(key, values);
291+
292+
bool result;
293+
KeyValuePair<string, int[]> resultPair;
294+
using (var cur = _txn.CreateCursor(_db))
295+
result = cur.MoveNextMultiple(out resultPair);
296+
297+
Assert.IsTrue(result);
298+
Assert.AreEqual(key, resultPair.Key);
299+
CollectionAssert.AreEqual(values, resultPair.Value);
300+
}
280301
}
281302
}

src/LightningDB/CursorGetByOperation.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace LightningDB
88
public class CursorGetByOperation
99
{
1010
private readonly LightningCursor _cur;
11-
private readonly KeyValuePair<byte[], byte[]>? _pair;
11+
private readonly KeyValuePair<GetByOperation, GetByOperation>? _pair;
1212

1313
/// <summary>
1414
/// Creates new instance of CursorGetByOperation.
@@ -18,7 +18,13 @@ public class CursorGetByOperation
1818
public CursorGetByOperation(LightningCursor cur, KeyValuePair<byte[], byte[]>? pair)
1919
{
2020
_cur = cur;
21-
_pair = pair;
21+
22+
if (pair.HasValue)
23+
{
24+
_pair = new KeyValuePair<GetByOperation, GetByOperation>(
25+
new GetByOperation(cur.Database, pair.Value.Key),
26+
new GetByOperation(cur.Database, pair.Value.Value));
27+
}
2228
}
2329

2430
/// <summary>
@@ -41,7 +47,7 @@ public TKey Key<TKey>()
4147
{
4248
this.EnsurePairExists();
4349

44-
return _cur.FromBytes<TKey>(_pair.Value.Key);
50+
return _pair.Value.Key.Value<TKey>();
4551
}
4652

4753
/// <summary>
@@ -53,7 +59,7 @@ public TValue Value<TValue>()
5359
{
5460
this.EnsurePairExists();
5561

56-
return _cur.FromBytes<TValue>(_pair.Value.Value);
62+
return _pair.Value.Value.Value<TValue>();
5763
}
5864

5965
/// <summary>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System;
2+
using System.Collections.Generic;
3+
namespace LightningDB
4+
{
5+
/// <summary>
6+
/// Converter class for pairs obtained via cursor
7+
/// </summary>
8+
public class CursorMultipleGetByOperation
9+
{
10+
private readonly LightningCursor _cur;
11+
private readonly KeyValuePair<GetByOperation, MultipleGetByOperation>? _pair;
12+
13+
/// <summary>
14+
/// Creates new instance of CursorGetByOperation.
15+
/// </summary>
16+
/// <param name="cur">Cursor.</param>
17+
/// <param name="pair">Key-value byte arrays pair</param>
18+
public CursorMultipleGetByOperation(LightningCursor cur, KeyValuePair<byte[], byte[]>? pair)
19+
{
20+
_cur = cur;
21+
22+
if (pair.HasValue)
23+
{
24+
_pair = new KeyValuePair<GetByOperation, MultipleGetByOperation>(
25+
new GetByOperation(cur.Database, pair.Value.Key),
26+
new MultipleGetByOperation(cur.Database, pair.Value.Value));
27+
}
28+
}
29+
30+
/// <summary>
31+
/// Does key-value pair exist in database.
32+
/// </summary>
33+
public bool PairExists { get { return _pair.HasValue; } }
34+
35+
private void EnsurePairExists()
36+
{
37+
if (!this.PairExists)
38+
throw new InvalidOperationException("Pair doesn't exist");
39+
}
40+
41+
/// <summary>
42+
/// Converts database key to a concrete type
43+
/// </summary>
44+
/// <typeparam name="TKey">Type to convert key to</typeparam>
45+
/// <returns>Converted key value.</returns>
46+
public TKey Key<TKey>()
47+
{
48+
this.EnsurePairExists();
49+
50+
return _pair.Value.Key.Value<TKey>();
51+
}
52+
53+
/// <summary>
54+
/// Converts database value to a concrete type.
55+
/// </summary>
56+
/// <typeparam name="TValue">Type to convert value to.</typeparam>
57+
/// <returns>Converted value.</returns>
58+
public TValue[] Values<TValue>()
59+
{
60+
this.EnsurePairExists();
61+
62+
return _pair.Value.Value.Values<TValue>();
63+
}
64+
65+
/// <summary>
66+
/// Convert key-value pair to concrete types
67+
/// </summary>
68+
/// <typeparam name="TKey">Key type.</typeparam>
69+
/// <typeparam name="TValue">Value type.</typeparam>
70+
/// <returns>Pair of converted key and value.</returns>
71+
public KeyValuePair<TKey, TValue[]> Pair<TKey, TValue>()
72+
{
73+
return new KeyValuePair<TKey, TValue[]>(this.Key<TKey>(), this.Values<TValue>());
74+
}
75+
}
76+
}

src/LightningDB/GetByOperation.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@ public GetByOperation(LightningDatabase db, byte[] rawValue)
2121
_rawValue = rawValue;
2222
}
2323

24+
public bool HasValue { get { return _rawValue != null; } }
25+
2426
/// <summary>
2527
/// Convert value from bytes to a specified type..
2628
/// </summary>
2729
/// <typeparam name="TValue">Target value type.</typeparam>
2830
/// <returns>Converted value.</returns>
2931
public TValue Value<TValue>()
3032
{
33+
if (!HasValue)
34+
throw new InvalidOperationException("Value doen't exist");
35+
3136
return _db.FromBytes<TValue>(_rawValue);
3237
}
3338
}

src/LightningDB/LightningCursor.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,9 @@ public byte[] GetMultiple()
192192
/// </summary>
193193
/// <remarks>Not sure what it should do and if the wrapper is correct</remarks>
194194
/// <returns>All duplicate data items at the next cursor position</returns>
195-
public byte[] MoveNextMultiple()
195+
public KeyValuePair<byte[], byte[]>? MoveNextMultiple()
196196
{
197-
var result = this.Get(CursorOperation.NextMultiple);
198-
if (!result.HasValue)
199-
return null;
200-
201-
return result.Value.Value;
197+
return this.Get(CursorOperation.NextMultiple);
202198
}
203199

204200
/// <summary>

src/LightningDB/LightningCursorExtensions.cs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,13 @@ public static void PutMultiple<TKey, TValue>(this LightningCursor cur, TKey key,
6767

6868
public static MultipleGetByOperation GetMultipleBy<TValue>(this LightningCursor cur)
6969
{
70-
var bytes = cur.GetMultiple();
71-
if (bytes == null)
72-
return null;
73-
74-
return new MultipleGetByOperation(cur.Database, bytes);
70+
return new MultipleGetByOperation(cur.Database, cur.GetMultiple());
7571
}
7672

7773
public static bool GetMultiple<TValue>(this LightningCursor cur, out TValue[] values)
7874
{
7975
var op = cur.GetMultipleBy<TValue>();
80-
if (op == null)
76+
if (!op.HasValue)
8177
{
8278
values = null;
8379
return false;
@@ -88,6 +84,26 @@ public static bool GetMultiple<TValue>(this LightningCursor cur, out TValue[] va
8884
return true;
8985
}
9086

87+
public static CursorMultipleGetByOperation MoveNextMultipleBy(this LightningCursor cur)
88+
{
89+
return new CursorMultipleGetByOperation(cur, cur.MoveNextMultiple());
90+
}
91+
92+
public static bool MoveNextMultiple<TKey, TValue>(this LightningCursor cur, out KeyValuePair<TKey, TValue[]> pair)
93+
{
94+
var op = cur.MoveNextMultipleBy();
95+
if (!op.PairExists)
96+
{
97+
pair = default(KeyValuePair<TKey, TValue[]>);
98+
return false;
99+
}
100+
else
101+
{
102+
pair = op.Pair<TKey, TValue>();
103+
return true;
104+
}
105+
}
106+
91107
internal static byte[] ToBytes<T>(this LightningCursor cur, T instance)
92108
{
93109
return cur.Database.ToBytes(instance);
@@ -105,11 +121,7 @@ internal static CursorGetByOperation CursorMoveBy(this LightningCursor cur, Func
105121

106122
internal static GetByOperation CursorMoveValueBy(this LightningCursor cur, Func<byte[]> mover)
107123
{
108-
var value = mover.Invoke();
109-
if (value == null)
110-
return null;
111-
112-
return new GetByOperation(cur.Database, value);
124+
return new GetByOperation(cur.Database, mover.Invoke());
113125
}
114126

115127
internal static bool CursorMove<TKey, TValue>(this LightningCursor cur, Func<KeyValuePair<byte[], byte[]>?> mover, out KeyValuePair<TKey, TValue> pair)

src/LightningDB/LightningDB.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
<Compile Include="Collections\CursorGenericEnumerable.cs" />
7373
<Compile Include="Collections\CursorEnumerable.cs" />
7474
<Compile Include="Collections\CursorEnumerator.cs" />
75+
<Compile Include="CursorMultipleGetByOperation.cs" />
7576
<Compile Include="MultipleGetByOperation.cs" />
7677
<Compile Include="LightningCompareDelegate.cs" />
7778
<Compile Include="CompareFunctionBuilder.cs" />

src/LightningDB/MultipleGetByOperation.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,18 @@ public MultipleGetByOperation(LightningDatabase db, byte[] rawValue)
2222
_rawValue = rawValue;
2323
}
2424

25+
public bool HasValue { get { return _rawValue != null; } }
26+
2527
/// <summary>
2628
/// Convert values from bytes to a specified type..
2729
/// </summary>
2830
/// <typeparam name="TValue">Target value type.</typeparam>
2931
/// <returns>Converted value.</returns>
3032
public TValue[] Values<TValue>()
3133
{
34+
if (!HasValue)
35+
throw new InvalidOperationException("Value doen't exist");
36+
3237
var itemSize = Marshal.SizeOf(typeof(TValue));
3338
if (_rawValue.Length % itemSize != 0)
3439
throw new InvalidOperationException("Returned " + _rawValue.Length + " bytes when expected N*" + itemSize + " bytes");

0 commit comments

Comments
 (0)