1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2009, 2013 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 using System;
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.Text;
11 using BerkeleyDB.Internal;
12 
13 namespace BerkeleyDB {
14     /// <summary>
15     /// A class representing database cursors over secondary indexes, which
16     /// allow for traversal of database records.
17     /// </summary>
18     public class SecondaryCursor
19         : BaseCursor, IEnumerable<KeyValuePair<DatabaseEntry,
20         KeyValuePair<DatabaseEntry, DatabaseEntry>>> {
21         private KeyValuePair<DatabaseEntry,
22             KeyValuePair<DatabaseEntry, DatabaseEntry>> cur;
23         /// <summary>
24         /// The secondary key and primary key/data pair at which the cursor
25         /// currently points.
26         /// </summary>
27         public KeyValuePair<DatabaseEntry,
28             KeyValuePair<DatabaseEntry, DatabaseEntry>> Current {
29             get { return cur; }
30             private set { cur = value; }
31         }
SecondaryCursor(DBC dbc)32         internal SecondaryCursor(DBC dbc) : base(dbc) { }
33 
34         /// <summary>
35         /// Protected method wrapping DBC->pget()
36         /// </summary>
37         /// <param name="key">The secondary key</param>
38         /// <param name="pkey">The primary key</param>
39         /// <param name="data">The primary data</param>
40         /// <param name="flags">Flags to pass to DBC->pget</param>
41         /// <param name="info">Locking parameters</param>
42         /// <returns></returns>
PGet( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, uint flags, LockingInfo info)43         protected bool PGet(
44             DatabaseEntry key, DatabaseEntry pkey,
45             DatabaseEntry data, uint flags, LockingInfo info) {
46             flags |= (info == null) ? 0 : info.flags;
47             try {
48                 dbc.pget(key, pkey, data, flags);
49                 Current = new KeyValuePair<DatabaseEntry,
50                     KeyValuePair<DatabaseEntry, DatabaseEntry>>(key,
51                     new KeyValuePair<DatabaseEntry, DatabaseEntry>(pkey, data));
52                 return true;
53             } catch (NotFoundException) {
54                 Current = new KeyValuePair<DatabaseEntry,
55                     KeyValuePair<DatabaseEntry, DatabaseEntry>>(
56                     null, new KeyValuePair<DatabaseEntry, DatabaseEntry>());
57                 return false;
58             }
59         }
60 
61         /// <summary>
62         /// Delete the key/data pair to which the cursor refers from the primary
63         /// database and all secondary indices.
64         /// </summary>
65         /// <remarks>
66         /// <para>
67         /// The cursor position is unchanged after a delete, and subsequent
68         /// calls to cursor functions expecting the cursor to refer to an
69         /// existing key will fail.
70         /// </para>
71         /// </remarks>
72         /// <exception cref="KeyEmptyException">
73         /// The element has already been deleted.
74         /// </exception>
Delete()75         public new void Delete() {
76             base.Delete();
77             Current =
78                 new KeyValuePair<DatabaseEntry,
79                 KeyValuePair<DatabaseEntry, DatabaseEntry>>(
80                 null, new KeyValuePair<DatabaseEntry, DatabaseEntry>());
81         }
82 
83         /// <summary>
84         /// Create a new cursor that uses the same transaction and locker ID as
85         /// the original cursor.
86         /// </summary>
87         /// <remarks>
88         /// This is useful when an application is using locking and requires two
89         /// or more cursors in the same thread of control.
90         /// </remarks>
91         /// <param name="keepPosition">
92         /// If true, the newly created cursor is initialized to refer to the
93         /// same position in the database as the original cursor (if any) and
94         /// hold the same locks (if any). If false, or the original cursor does
95         /// not hold a database position and locks, the created cursor is
96         /// uninitialized and will behave like a cursor newly created by
97         /// <see cref="BaseDatabase.Cursor"/>.</param>
98         /// <returns>A newly created cursor</returns>
Duplicate(bool keepPosition)99         public SecondaryCursor Duplicate(bool keepPosition) {
100             return new SecondaryCursor(
101                 dbc.dup(keepPosition ? DbConstants.DB_POSITION : 0));
102         }
103 
IEnumerable.GetEnumerator()104         IEnumerator IEnumerable.GetEnumerator() {
105             return GetEnumerator();
106         }
107 
108         /// <summary>
109         /// Returns an enumerator that iterates through the
110         /// <see cref="SecondaryCursor"/>.
111         /// </summary>
112         /// <remarks>
113         /// The enumerator will begin at the cursor's current position (or the
114         /// first record if the cursor has not yet been positioned) and iterate
115         /// forwards (i.e. in the direction of <see cref="MoveNext"/>) over the
116         /// remaining records.
117         /// </remarks>
118         /// <returns>An enumerator for the SecondaryCursor.</returns>
119         public new IEnumerator<KeyValuePair<DatabaseEntry,
GetEnumerator()120             KeyValuePair<DatabaseEntry, DatabaseEntry>>> GetEnumerator() {
121             while (MoveNext())
122                 yield return Current;
123         }
124 
125         /// <summary>
126         /// Set the cursor to refer to the first key/data pair of the database,
127         /// and store the secondary key along with the corresponding primary
128         /// key/data pair in <see cref="Current"/>. If the first key has
129         /// duplicate values, the first data item in the set of duplicates is
130         /// stored in <see cref="Current"/>.
131         /// </summary>
132         /// <remarks>
133         /// If positioning the cursor fails, <see cref="Current"/> will contain
134         /// an empty <see cref="KeyValuePair{T,T}"/>.
135         /// </remarks>
136         /// <returns>
137         /// True if the cursor was positioned successfully, false otherwise.
138         /// </returns>
MoveFirst()139         public bool MoveFirst() { return MoveFirst(null); }
140         /// <summary>
141         /// Set the cursor to refer to the first key/data pair of the database,
142         /// and store the secondary key along with the corresponding primary
143         /// key/data pair in <see cref="Current"/>. If the first key has
144         /// duplicate values, the first data item in the set of duplicates is
145         /// stored in <see cref="Current"/>.
146         /// </summary>
147         /// <remarks>
148         /// If positioning the cursor fails, <see cref="Current"/> will contain
149         /// an empty <see cref="KeyValuePair{T,T}"/>.
150         /// </remarks>
151         /// <param name="info">The locking behavior to use.</param>
152         /// <returns>
153         /// True if the cursor was positioned successfully, false otherwise.
154         /// </returns>
MoveFirst(LockingInfo info)155         public bool MoveFirst(LockingInfo info) {
156             DatabaseEntry key = new DatabaseEntry();
157             DatabaseEntry pkey = new DatabaseEntry();
158             DatabaseEntry data = new DatabaseEntry();
159 
160             return MoveFirst(key, pkey, data, info);
161         }
162         /// <summary>
163         /// Set the cursor to refer to the first key/data pair of the database,
164         /// and store the secondary key along with the corresponding primary
165         /// key/data pair in <see cref="Current"/>. If the first key has
166         /// duplicate values, the first data item in the set of duplicates is
167         /// stored in <see cref="Current"/>. If <paramref name="key"/>, or
168         /// <paramref name="pkey"/>, or <paramref name="data"/> is
169         /// partial <see cref="DatabaseEntry"/>, its
170         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
171         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
172         /// of the retrieved data record are returned as if they comprised the
173         /// entire record. If any or all of the specified bytes do not exist
174         /// in the record, MoveFirst is successful, and any existing bytes are
175         /// returned.
176         /// </summary>
177         /// <remarks>
178         /// If positioning the cursor fails, <see cref="Current"/> will contain
179         /// an empty <see cref="KeyValuePair{T,T}"/>.
180         /// </remarks>
181         /// <param name="key">The retrieved key in secondary db</param>
182         /// <param name="pkey">The retrieved key in primary db</param>
183         /// <param name="data">The retrieved data in primary db</param>
184         /// <returns>
185         /// True if the cursor was positioned successfully, false otherwise.
186         /// </returns>
MoveFirst( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)187         public bool MoveFirst(
188             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
189             return MoveFirst(key, pkey, data, null);
190         }
191         /// <summary>
192         /// Set the cursor to refer to the first key/data pair of the database,
193         /// and store the secondary key along with the corresponding primary
194         /// key/data pair in <see cref="Current"/>. If the first key has
195         /// duplicate values, the first data item in the set of duplicates is
196         /// stored in <see cref="Current"/>. If <paramref name="key"/>, or
197         /// <paramref name="pkey"/>, or <paramref name="data"/> is
198         /// partial <see cref="DatabaseEntry"/>, its
199         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
200         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
201         /// of the retrieved data record are returned as if they comprised the
202         /// entire record. If any or all of the specified bytes do not exist
203         /// in the record, MoveFirst is successful, and any existing bytes are
204         /// returned.
205         /// </summary>
206         /// <remarks>
207         /// If positioning the cursor fails, <see cref="Current"/> will contain
208         /// an empty <see cref="KeyValuePair{T,T}"/>.
209         /// </remarks>
210         /// <param name="key">The retrieved key in secondary db</param>
211         /// <param name="pkey">The retrieved key in primary db</param>
212         /// <param name="data">The retrieved data in primary db</param>
213         /// <param name="info">The locking behavior to use.</param>
214         /// <returns>
215         /// True if the cursor was positioned successfully, false otherwise.
216         /// </returns>
MoveFirst(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)217         public bool MoveFirst(DatabaseEntry key, DatabaseEntry pkey,
218             DatabaseEntry data, LockingInfo info) {
219             return PGet(key, pkey, data, DbConstants.DB_FIRST, info);
220         }
221 
222         /// <summary>
223         /// Set the cursor to refer to <paramref name="key"/>, and store the
224         /// primary key/data pair associated with the given secondary key in
225         /// <see cref="Current"/>. In the presence of duplicate key values, the
226         /// first data item in the set of duplicates is stored in
227         /// <see cref="Current"/>.
228         /// </summary>
229         /// <remarks>
230         /// If positioning the cursor fails, <see cref="Current"/> will contain
231         /// an empty <see cref="KeyValuePair{T,T}"/>.
232         /// </remarks>
233         /// <param name="key">The key at which to position the cursor</param>
234         /// <param name="exact">
235         /// If false and in a database configured for sorted duplicates,
236         /// position the cursor at the smallest key greater than or equal to the
237         /// specified key, permitting partial key matches and range searches.
238         /// Otherwise, require the given key to match the key in the database
239         /// exactly.
240         /// </param>
241         /// <returns>
242         /// True if the cursor was positioned successfully, false otherwise.
243         /// </returns>
Move(DatabaseEntry key, bool exact)244         public bool Move(DatabaseEntry key, bool exact) {
245             return Move(key, exact, null);
246         }
247         /// <summary>
248         /// Set the cursor to refer to <paramref name="key"/>, and store the
249         /// primary key/data pair associated with the given secondary key in
250         /// <see cref="Current"/>. In the presence of duplicate key values, the
251         /// first data item in the set of duplicates is stored in
252         /// <see cref="Current"/>.
253         /// </summary>
254         /// <remarks>
255         /// If positioning the cursor fails, <see cref="Current"/> will contain
256         /// an empty <see cref="KeyValuePair{T,T}"/>.
257         /// </remarks>
258         /// <param name="key">The key at which to position the cursor</param>
259         /// <param name="exact">
260         /// If false and in a database configured for sorted duplicates,
261         /// position the cursor at the smallest key greater than or equal to the
262         /// specified key, permitting partial key matches and range searches.
263         /// Otherwise, require the given key to match the key in the database
264         /// exactly.
265         /// </param>
266         /// <param name="info">The locking behavior to use.</param>
267         /// <returns>
268         /// True if the cursor was positioned successfully, false otherwise.
269         /// </returns>
Move(DatabaseEntry key, bool exact, LockingInfo info)270         public bool Move(DatabaseEntry key, bool exact, LockingInfo info) {
271             DatabaseEntry pkey = new DatabaseEntry();
272             DatabaseEntry data = new DatabaseEntry();
273 
274             return Move(key, pkey, data, exact, info);
275         }
276         /// <summary>
277         /// Set the cursor to refer to <paramref name="key"/>, and store the
278         /// primary key/data pair associated with the given secondary key in
279         /// <see cref="Current"/>. In the presence of duplicate key values, the
280         /// first data item in the set of duplicates is stored in
281         /// <see cref="Current"/>. If <paramref name="key"/>, or
282         /// <paramref name="pkey"/>, or <paramref name="data"/> is
283         /// partial <see cref="DatabaseEntry"/>, its
284         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
285         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
286         /// of the retrieved data record are returned as if they comprised the
287         /// entire record. If any or all of the specified bytes do not exist
288         /// in the record, Move is successful, and any existing bytes are
289         /// returned.
290         /// </summary>
291         /// <remarks>
292         /// If positioning the cursor fails, <see cref="Current"/> will contain
293         /// an empty <see cref="KeyValuePair{T,T}"/>.
294         /// </remarks>
295         /// <param name="key">The key at which to position the cursor</param>
296         /// <param name="pkey">
297         /// The key of the current matching record in primary db
298         /// </param>
299         /// <param name="data">
300         /// The data of the current matching record in primary db
301         /// </param>
302         /// <param name="exact">
303         /// If false and in a database configured for sorted duplicates,
304         /// position the cursor at the smallest key greater than or equal to the
305         /// specified key, permitting partial key matches and range searches.
306         /// Otherwise, require the given key to match the key in the database
307         /// exactly.
308         /// </param>
309         /// <returns>
310         /// True if the cursor was positioned successfully, false otherwise.
311         /// </returns>
Move(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, bool exact)312         public bool Move(DatabaseEntry key, DatabaseEntry pkey,
313             DatabaseEntry data, bool exact) {
314             return Move(key, pkey, data, exact, null);
315         }
316         /// <summary>
317         /// Set the cursor to refer to <paramref name="key"/>, and store the
318         /// primary key/data pair associated with the given secondary key in
319         /// <see cref="Current"/>. In the presence of duplicate key values, the
320         /// first data item in the set of duplicates is stored in
321         /// <see cref="Current"/>. If <paramref name="key"/>, or
322         /// <paramref name="pkey"/>, or <paramref name="data"/> is
323         /// partial <see cref="DatabaseEntry"/>, its
324         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
325         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
326         /// of the retrieved data record are returned as if they comprised the
327         /// entire record. If any or all of the specified bytes do not exist
328         /// in the record, Move is successful, and any existing bytes are
329         /// returned.
330         /// </summary>
331         /// <remarks>
332         /// If positioning the cursor fails, <see cref="Current"/> will contain
333         /// an empty <see cref="KeyValuePair{T,T}"/>.
334         /// </remarks>
335         /// <param name="key">The key at which to position the cursor</param>
336         /// <param name="pkey">
337         /// The key of the current matching record in primary db
338         /// </param>
339         /// <param name="data">
340         /// The data of the current matching record in primary db
341         /// </param>
342         /// <param name="exact">
343         /// If false and in a database configured for sorted duplicates,
344         /// position the cursor at the smallest key greater than or equal to the
345         /// specified key, permitting partial key matches and range searches.
346         /// Otherwise, require the given key to match the key in the database
347         /// exactly.
348         /// </param>
349         /// <param name="info">The locking behavior to use.</param>
350         /// <returns>
351         /// True if the cursor was positioned successfully, false otherwise.
352         /// </returns>
Move(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, bool exact, LockingInfo info)353         public bool Move(DatabaseEntry key, DatabaseEntry pkey,
354             DatabaseEntry data, bool exact, LockingInfo info) {
355             return PGet(key, pkey, data,
356                 exact ? DbConstants.DB_SET : DbConstants.DB_SET_RANGE, info);
357         }
358 
359         /// <summary>
360         /// Move the cursor to the specified key/data pair of the database. The
361         /// cursor is positioned to a key/data pair if both the key and data
362         /// match the values provided on the key and data parameters.
363         /// </summary>
364         /// <remarks>
365         /// <para>
366         /// If positioning the cursor fails, <see cref="Current"/> will contain
367         /// an empty <see cref="KeyValuePair{T,T}"/>.
368         /// </para>
369         /// <para>
370         /// If this flag is specified on a database configured without sorted
371         /// duplicate support, the value of <paramref name="exact"/> is ignored.
372         /// </para>
373         /// </remarks>
374         /// <param name="pair">
375         /// The key/data pair at which to position the cursor.
376         /// </param>
377         /// <param name="exact">
378         /// If false and in a database configured for sorted duplicates,
379         /// position the cursor at the smallest data value which is greater than
380         /// or equal to the value provided by <paramref name="pair"/>.Value (as
381         /// determined by the comparison function). Otherwise, require the given
382         /// key and data to match the key and data in the database exactly.
383         /// </param>
384         /// <returns>
385         /// True if the cursor was positioned successfully, false otherwise.
386         /// </returns>
Move(KeyValuePair<DatabaseEntry, KeyValuePair<DatabaseEntry, DatabaseEntry>> pair, bool exact)387         public bool Move(KeyValuePair<DatabaseEntry,
388             KeyValuePair<DatabaseEntry, DatabaseEntry>> pair, bool exact) {
389             return Move(pair, exact, null);
390         }
391         /// <summary>
392         /// Move the cursor to the specified key/data pair of the database. The
393         /// cursor is positioned to a key/data pair if both the key and data
394         /// match the values provided on the key and data parameters.
395         /// </summary>
396         /// <remarks>
397         /// <para>
398         /// If positioning the cursor fails, <see cref="Current"/> will contain
399         /// an empty <see cref="KeyValuePair{T,T}"/>.
400         /// </para>
401         /// <para>
402         /// If this flag is specified on a database configured without sorted
403         /// duplicate support, the value of <paramref name="exact"/> is ignored.
404         /// </para>
405         /// </remarks>
406         /// <param name="pair">
407         /// The key/data pair at which to position the cursor.
408         /// </param>
409         /// <param name="exact">
410         /// If false and in a database configured for sorted duplicates,
411         /// position the cursor at the smallest data value which is greater than
412         /// or equal to the value provided by <paramref name="pair"/>.Value (as
413         /// determined by the comparison function). Otherwise, require the given
414         /// key and data to match the key and data in the database exactly.
415         /// </param>
416         /// <param name="info">The locking behavior to use.</param>
417         /// <returns>
418         /// True if the cursor was positioned successfully, false otherwise.
419         /// </returns>
Move(KeyValuePair<DatabaseEntry, KeyValuePair<DatabaseEntry, DatabaseEntry>> pair, bool exact, LockingInfo info)420         public bool Move(KeyValuePair<DatabaseEntry,
421             KeyValuePair<DatabaseEntry, DatabaseEntry>> pair,
422             bool exact, LockingInfo info) {
423             return PGet(pair.Key, pair.Value.Key, pair.Value.Value, exact ?
424                 DbConstants.DB_GET_BOTH : DbConstants.DB_GET_BOTH_RANGE, info);
425         }
426 
427         /// <summary>
428         /// Set the cursor to refer to the last key/data pair of the database,
429         /// and store the secondary key and primary key/data pair in
430         /// <see cref="Current"/>. If the last key has duplicate values, the
431         /// last data item in the set of duplicates is stored in
432         /// <see cref="Current"/>.
433         /// </summary>
434         /// <remarks>
435         /// If positioning the cursor fails, <see cref="Current"/> will contain
436         /// an empty <see cref="KeyValuePair{T,T}"/>.
437         /// </remarks>
438         /// <returns>
439         /// True if the cursor was positioned successfully, false otherwise.
440         /// </returns>
MoveLast()441         public bool MoveLast() { return MoveLast(null); }
442         /// <summary>
443         /// Set the cursor to refer to the last key/data pair of the database,
444         /// and store the secondary key and primary key/data pair in
445         /// <see cref="Current"/>. If the last key has duplicate values, the
446         /// last data item in the set of duplicates is stored in
447         /// <see cref="Current"/>.
448         /// </summary>
449         /// <remarks>
450         /// If positioning the cursor fails, <see cref="Current"/> will contain
451         /// an empty <see cref="KeyValuePair{T,T}"/>.
452         /// </remarks>
453         /// <param name="info">The locking behavior to use.</param>
454         /// <returns>
455         /// True if the cursor was positioned successfully, false otherwise.
456         /// </returns>
MoveLast(LockingInfo info)457         public bool MoveLast(LockingInfo info) {
458             DatabaseEntry key = new DatabaseEntry();
459             DatabaseEntry pkey = new DatabaseEntry();
460             DatabaseEntry data = new DatabaseEntry();
461 
462             return MoveLast(key, pkey, data, info);
463         }
464         /// <summary>
465         /// Set the cursor to refer to the last key/data pair of the database,
466         /// and store the secondary key and primary key/data pair in
467         /// <see cref="Current"/>. If the last key has duplicate values, the
468         /// last data item in the set of duplicates is stored in
469         /// <see cref="Current"/>. If <paramref name="key"/>, or
470         /// <paramref name="pkey"/>, or <paramref name="data"/> is
471         /// partial <see cref="DatabaseEntry"/>, its
472         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
473         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
474         /// of the retrieved data record are returned as if they comprised the
475         /// entire record. If any or all of the specified bytes do not exist
476         /// in the record, MoveLast is successful, and any existing bytes are
477         /// returned.
478         /// </summary>
479         /// <remarks>
480         /// If positioning the cursor fails, <see cref="Current"/> will contain
481         /// an empty <see cref="KeyValuePair{T,T}"/>.
482         /// </remarks>
483         /// <param name="key">The retrieved key in secondary db</param>
484         /// <param name="pkey">
485         /// The key of the matching record in primary db
486         /// </param>
487         /// <param name="data">
488         /// The data of the matching record in primary db
489         /// </param>
490         /// <returns>
491         /// True if the cursor was positioned successfully, false otherwise.
492         /// </returns>
MoveLast( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)493         public bool MoveLast(
494             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
495             return MoveLast(key, pkey, data, null);
496         }
497         /// <summary>
498         /// Set the cursor to refer to the last key/data pair of the database,
499         /// and store the secondary key and primary key/data pair in
500         /// <see cref="Current"/>. If the last key has duplicate values, the
501         /// last data item in the set of duplicates is stored in
502         /// <see cref="Current"/>. If <paramref name="key"/>, or
503         /// <paramref name="pkey"/>, or <paramref name="data"/> is
504         /// partial <see cref="DatabaseEntry"/>, its
505         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
506         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
507         /// of the retrieved data record are returned as if they comprised the
508         /// entire record. If any or all of the specified bytes do not exist
509         /// in the record, MoveLast is successful, and any existing bytes are
510         /// returned.
511         /// </summary>
512         /// <remarks>
513         /// If positioning the cursor fails, <see cref="Current"/> will contain
514         /// an empty <see cref="KeyValuePair{T,T}"/>.
515         /// </remarks>
516         /// <param name="key">The retrieved key in secondary db</param>
517         /// <param name="pkey">
518         /// The key of the matching record in primary db
519         /// </param>
520         /// <param name="data">
521         /// The data of the matching record in primary db
522         /// </param>
523         /// <param name="info">The locking behavior to use</param>
524         /// <returns>
525         /// True if the cursor was positioned successfully, false otherwise.
526         /// </returns>
MoveLast(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)527         public bool MoveLast(DatabaseEntry key, DatabaseEntry pkey,
528             DatabaseEntry data, LockingInfo info) {
529             return PGet(key, pkey, data, DbConstants.DB_LAST, info);
530         }
531 
532         /// <summary>
533         /// If the cursor is not yet initialized, MoveNext is identical to
534         /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next
535         /// key/data pair of the database, and store the secondary key and
536         /// primary key/data pair in <see cref="Current"/>. In the presence of
537         /// duplicate key values, the value of <see cref="Current">Current.Key
538         /// </see> may not change.
539         /// </summary>
540         /// <remarks>
541         /// If positioning the cursor fails, <see cref="Current"/> will contain
542         /// an empty <see cref="KeyValuePair{T,T}"/>.
543         /// </remarks>
544         /// <returns>
545         /// True if the cursor was positioned successfully, false otherwise.
546         /// </returns>
MoveNext()547         public bool MoveNext() { return MoveNext(null); }
548         /// <summary>
549         /// If the cursor is not yet initialized, MoveNext is identical to
550         /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next
551         /// key/data pair of the database, and store the secondary key and
552         /// primary key/data pair in <see cref="Current"/>. In the presence of
553         /// duplicate key values, the value of <see cref="Current">Current.Key
554         /// </see> may not change.
555         /// </summary>
556         /// <remarks>
557         /// If positioning the cursor fails, <see cref="Current"/> will contain
558         /// an empty <see cref="KeyValuePair{T,T}"/>.
559         /// </remarks>
560         /// <param name="info">The locking behavior to use.</param>
561         /// <returns>
562         /// True if the cursor was positioned successfully, false otherwise.
563         /// </returns>
MoveNext(LockingInfo info)564         public bool MoveNext(LockingInfo info) {
565             DatabaseEntry key = new DatabaseEntry();
566             DatabaseEntry pkey = new DatabaseEntry();
567             DatabaseEntry data = new DatabaseEntry();
568 
569             return MoveNext(key, pkey, data, info);
570         }
571         /// <summary>
572         /// If the cursor is not yet initialized, MoveNext is identical to
573         /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next
574         /// key/data pair of the database, and store the secondary key and
575         /// primary key/data pair in <see cref="Current"/>. In the presence of
576         /// duplicate key values, the value of <see cref="Current">Current.Key
577         /// </see> may not change. If <paramref name="key"/>, or
578         /// <paramref name="pkey"/>, or <paramref name="data"/> is
579         /// partial <see cref="DatabaseEntry"/>, its
580         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
581         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
582         /// of the retrieved data record are returned as if they comprised the
583         /// entire record. If any or all of the specified bytes do not exist
584         /// in the record, MoveNext is successful, and any existing bytes are
585         /// returned.
586         /// </summary>
587         /// <remarks>
588         /// If positioning the cursor fails, <see cref="Current"/> will contain
589         /// an empty <see cref="KeyValuePair{T,T}"/>.
590         /// </remarks>
591         /// <param name="key">The retrieved key in secondary db</param>
592         /// <param name="pkey">
593         /// The key of the matching record in primary db
594         /// </param>
595         /// <param name="data">
596         /// The data of the matching record in primary db
597         /// </param>
598         /// <returns>
599         /// True if the cursor was positioned successfully, false otherwise.
600         /// </returns>
MoveNext( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)601         public bool MoveNext(
602             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
603             return MoveNext(key, pkey, data, null);
604         }
605         /// <summary>
606         /// If the cursor is not yet initialized, MoveNext is identical to
607         /// <see cref="MoveFirst(LockingInfo)"/>. Otherwise, move the cursor
608         /// to the next key/data pair of the database, and store the secondary
609         /// key and primary key/data pair in <see cref="Current"/>. In the
610         /// presence of duplicate key values, the value of <see cref="Current">
611         /// Current.Key </see> may not change. If <paramref name="key"/>, or
612         /// <paramref name="pkey"/>, or <paramref name="data"/> is
613         /// partial <see cref="DatabaseEntry"/>, its
614         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
615         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
616         /// of the retrieved data record are returned as if they comprised the
617         /// entire record. If any or all of the specified bytes do not exist
618         /// in the record, MoveNext is successful, and any existing bytes are
619         /// returned.
620         /// </summary>
621         /// <remarks>
622         /// If positioning the cursor fails, <see cref="Current"/> will contain
623         /// an empty <see cref="KeyValuePair{T,T}"/>.
624         /// </remarks>
625         /// <param name="key">The retrieved key in secondary db</param>
626         /// <param name="pkey">
627         /// The key of the matching record in primary db
628         /// </param>
629         /// <param name="data">
630         /// The data of the matching record in primary db
631         /// </param>
632         /// <param name="info">The locking behavior to use</param>
633         /// <returns>
634         /// True if the cursor was positioned successfully, false otherwise.
635         /// </returns>
MoveNext(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)636         public bool MoveNext(DatabaseEntry key, DatabaseEntry pkey,
637             DatabaseEntry data, LockingInfo info) {
638             return PGet(key, pkey, data, DbConstants.DB_NEXT, info);
639         }
640 
641         /// <summary>
642         /// If the next key/data pair of the database is a duplicate data record
643         /// for the current key/data pair, move the cursor to the next key/data
644         /// pair in the database, and store the secondary key and primary
645         /// key/data pair in <see cref="Current"/>. MoveNextDuplicate will
646         /// return false if the next key/data pair of the database is not a
647         /// duplicate data record for the current key/data pair.
648         /// </summary>
649         /// <remarks>
650         /// If positioning the cursor fails, <see cref="Current"/> will contain
651         /// an empty <see cref="KeyValuePair{T,T}"/>.
652         /// </remarks>
653         /// <returns>
654         /// True if the cursor was positioned successfully, false otherwise.
655         /// </returns>
MoveNextDuplicate()656         public bool MoveNextDuplicate() { return MoveNextDuplicate(null); }
657         /// <summary>
658         /// If the next key/data pair of the database is a duplicate data record
659         /// for the current key/data pair, move the cursor to the next key/data
660         /// pair in the database, and store the secondary key and primary
661         /// key/data pair in <see cref="Current"/>. MoveNextDuplicate will
662         /// return false if the next key/data pair of the database is not a
663         /// duplicate data record for the current key/data pair.
664         /// </summary>
665         /// <remarks>
666         /// If positioning the cursor fails, <see cref="Current"/> will contain
667         /// an empty <see cref="KeyValuePair{T,T}"/>.
668         /// </remarks>
669         /// <param name="info">The locking behavior to use.</param>
670         /// <returns>
671         /// True if the cursor was positioned successfully, false otherwise.
672         /// </returns>
MoveNextDuplicate(LockingInfo info)673         public bool MoveNextDuplicate(LockingInfo info) {
674             DatabaseEntry key = new DatabaseEntry();
675             DatabaseEntry pkey = new DatabaseEntry();
676             DatabaseEntry data = new DatabaseEntry();
677 
678             return MoveNextDuplicate(key, pkey, data, info);
679         }
680         /// <summary>
681         /// If the next key/data pair of the database is a duplicate data record
682         /// for the current key/data pair, move the cursor to the next key/data
683         /// pair in the database, and store the secondary key and primary
684         /// key/data pair in <see cref="Current"/>. MoveNextDuplicate will
685         /// return false if the next key/data pair of the database is not a
686         /// duplicate data record for the current key/data pair. If
687         /// <paramref name="key"/>, or <paramref name="pkey"/>, or
688         /// <paramref name="data"/> is partial <see cref="DatabaseEntry"/>,
689         /// its <see cref="DatabaseEntry.PartialLen"/> bytes starting
690         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
691         /// of the retrieved data record are returned as if they comprised the
692         /// entire record. If any or all of the specified bytes do not exist
693         /// in the record, MoveNextDuplicate is successful, and any existing bytes are
694         /// returned.
695         /// </summary>
696         /// <remarks>
697         /// If positioning the cursor fails, <see cref="Current"/> will contain
698         /// an empty <see cref="KeyValuePair{T,T}"/>.
699         /// </remarks>
700         /// <param name="key">The retrieved key in secondary db</param>
701         /// <param name="pkey">
702         /// The key of the matching record in primary db
703         /// </param>
704         /// <param name="data">
705         /// The data of the matching record in primary db
706         /// </param>
707         /// <returns>
708         /// True if the cursor was positioned successfully, false otherwise.
709         /// </returns>
MoveNextDuplicate( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)710         public bool MoveNextDuplicate(
711             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
712             return MoveNextDuplicate(key, pkey, data, null);
713         }
714         /// <summary>
715         /// If the next key/data pair of the database is a duplicate data record
716         /// for the current key/data pair, move the cursor to the next key/data
717         /// pair in the database, and store the secondary key and primary
718         /// key/data pair in <see cref="Current"/>. MoveNextDuplicate will
719         /// return false if the next key/data pair of the database is not a
720         /// duplicate data record for the current key/data pair. If
721         /// <paramref name="key"/>, or <paramref name="pkey"/>, or
722         /// <paramref name="data"/> is partial <see cref="DatabaseEntry"/>,
723         /// its <see cref="DatabaseEntry.PartialLen"/> bytes starting
724         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
725         /// of the retrieved data record are returned as if they comprised the
726         /// entire record. If any or all of the specified bytes do not exist
727         /// in the record, MoveNextDuplicate is successful, and any existing bytes are
728         /// returned.
729         /// </summary>
730         /// <remarks>
731         /// If positioning the cursor fails, <see cref="Current"/> will contain
732         /// an empty <see cref="KeyValuePair{T,T}"/>.
733         /// </remarks>
734         /// <param name="key">The retrieved key in secondary db</param>
735         /// <param name="pkey">
736         /// The key of the matching record in primary db
737         /// </param>
738         /// <param name="data">
739         /// The data of the matching record in primary db
740         /// </param>
741         /// <param name="info">The locking behavior to use</param>
742         /// <returns>
743         /// True if the cursor was positioned successfully, false otherwise.
744         /// </returns>
MoveNextDuplicate(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)745         public bool MoveNextDuplicate(DatabaseEntry key, DatabaseEntry pkey,
746             DatabaseEntry data, LockingInfo info) {
747             return PGet(key, pkey, data, DbConstants.DB_NEXT_DUP, info);
748         }
749 
750         /// <summary>
751         /// If the cursor is not yet initialized, MoveNextUnique is identical to
752         /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next
753         /// non-duplicate key in the database, and store the secondary key and
754         /// primary key/data pair in <see cref="Current"/>. MoveNextUnique will
755         /// return false if no non-duplicate key/data pairs exist after the
756         /// cursor position in the database.
757         /// </summary>
758         /// <remarks>
759         /// If positioning the cursor fails, <see cref="Current"/> will contain
760         /// an empty <see cref="KeyValuePair{T,T}"/>.
761         /// </remarks>
762         /// <returns>
763         /// True if the cursor was positioned successfully, false otherwise.
764         /// </returns>
MoveNextUnique()765         public bool MoveNextUnique() { return MoveNextUnique(null); }
766         /// <summary>
767         /// If the cursor is not yet initialized, MoveNextUnique is identical to
768         /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next
769         /// non-duplicate key in the database, and store the secondary key and
770         /// primary key/data pair in <see cref="Current"/>. MoveNextUnique will
771         /// return false if no non-duplicate key/data pairs exist after the
772         /// cursor position in the database.
773         /// </summary>
774         /// <remarks>
775         /// <para>
776         /// If the database is a Queue or Recno database, MoveNextUnique will
777         /// ignore any keys that exist but were never explicitly created by the
778         /// application, or those that were created and later deleted.
779         /// </para>
780         /// <para>
781         /// If positioning the cursor fails, <see cref="Current"/> will contain
782         /// an empty <see cref="KeyValuePair{T,T}"/>.
783         /// </para>
784         /// </remarks>
785         /// <param name="info">The locking behavior to use.</param>
786         /// <returns>
787         /// True if the cursor was positioned successfully, false otherwise.
788         /// </returns>
MoveNextUnique(LockingInfo info)789         public bool MoveNextUnique(LockingInfo info) {
790             DatabaseEntry key = new DatabaseEntry();
791             DatabaseEntry pkey = new DatabaseEntry();
792             DatabaseEntry data = new DatabaseEntry();
793 
794             return MoveNextUnique(key, pkey, data, info);
795         }
796         /// <summary>
797         /// If the cursor is not yet initialized, MoveNextUnique is identical to
798         /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next
799         /// non-duplicate key in the database, and store the secondary key and
800         /// primary key/data pair in <see cref="Current"/>. MoveNextUnique will
801         /// return false if no non-duplicate key/data pairs exist after the
802         /// cursor position in the database. If <paramref name="key"/>, or
803         /// <paramref name="pkey"/>, or <paramref name="data"/> is
804         /// partial <see cref="DatabaseEntry"/>, its
805         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
806         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
807         /// of the retrieved data record are returned as if they comprised the
808         /// entire record. If any or all of the specified bytes do not exist
809         /// in the record, MoveNextUnique is successful, and any existing bytes
810         /// are returned.
811         /// </summary>
812         /// <remarks>
813         /// If positioning the cursor fails, <see cref="Current"/> will contain
814         /// an empty <see cref="KeyValuePair{T,T}"/>.
815         /// </remarks>
816         /// <param name="key">The retrieved key in secondary db</param>
817         /// <param name="pkey">
818         /// The key of the matching record in primary db
819         /// </param>
820         /// <param name="data">
821         /// The data of the matching record in primary db
822         /// </param>
823         /// <returns>
824         /// True if the cursor was positioned successfully, false otherwise.
825         /// </returns>
MoveNextUnique( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)826         public bool MoveNextUnique(
827             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
828             return MoveNextUnique(key, pkey, data, null);
829         }
830         /// <summary>
831         /// If the cursor is not yet initialized, MoveNextUnique is identical to
832         /// <see cref="MoveFirst(LockingInfo)"/>. Otherwise, move the cursor to
833         /// the next non-duplicate key in the database, and store the secondary
834         /// key and primary key/data pair in <see cref="Current"/>.
835         /// MoveNextUnique will return false if no non-duplicate key/data pairs
836         /// exist after the cursor position in the database. If
837         /// <paramref name="key"/>, or <paramref name="pkey"/>, or
838         /// <paramref name="data"/> is partial <see cref="DatabaseEntry"/>, its
839         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
840         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
841         /// of the retrieved data record are returned as if they comprised the
842         /// entire record. If any or all of the specified bytes do not exist
843         /// in the record, MoveNextUnique is successful, and any existing bytes
844         /// are returned.
845         /// </summary>
846         /// <remarks>
847         /// If positioning the cursor fails, <see cref="Current"/> will contain
848         /// an empty <see cref="KeyValuePair{T,T}"/>.
849         /// </remarks>
850         /// <param name="key">The retrieved key in secondary db</param>
851         /// <param name="pkey">
852         /// The key of the matching record in primary db
853         /// </param>
854         /// <param name="data">
855         /// The data of the matching record in primary db
856         /// </param>
857         /// <param name="info">The locking behavior to use</param>
858         /// <returns>
859         /// True if the cursor was positioned successfully, false otherwise.
860         /// </returns>
MoveNextUnique(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)861         public bool MoveNextUnique(DatabaseEntry key, DatabaseEntry pkey,
862             DatabaseEntry data, LockingInfo info) {
863             return PGet(key, pkey, data, DbConstants.DB_NEXT_NODUP, info);
864         }
865 
866         /// <summary>
867         /// If the cursor is not yet initialized, MovePrev is identical to
868         /// <see cref="MoveLast()"/>. Otherwise, move the cursor to the previous
869         /// key/data pair of the database, and store the secondary key and
870         /// primary key/data pair in <see cref="Current"/>. In the presence of
871         /// duplicate key values, the value of <see cref="Current">Current.Key
872         /// </see> may not change.
873         /// </summary>
874         /// <remarks>
875         /// If positioning the cursor fails, <see cref="Current"/> will contain
876         /// an empty <see cref="KeyValuePair{T,T}"/>.
877         /// </remarks>
878         /// <returns>
879         /// True if the cursor was positioned successfully, false otherwise.
880         /// </returns>
MovePrev()881         public bool MovePrev() { return MovePrev(null); }
882         /// <summary>
883         /// If the cursor is not yet initialized, MovePrev is identical to
884         /// <see cref="MoveLast(LockingInfo)"/>. Otherwise, move the cursor to
885         /// the previous key/data pair of the database, and store the secondary
886         /// key and primary key/data pair in <see cref="Current"/>. In the
887         /// presence of duplicate key values, the value of <see cref="Current">
888         /// Current.Key</see> may not change.
889         /// </summary>
890         /// <remarks>
891         /// If positioning the cursor fails, <see cref="Current"/> will contain
892         /// an empty <see cref="KeyValuePair{T,T}"/>.
893         /// </remarks>
894         /// <param name="info">The locking behavior to use.</param>
895         /// <returns>
896         /// True if the cursor was positioned successfully, false otherwise.
897         /// </returns>
MovePrev(LockingInfo info)898         public bool MovePrev(LockingInfo info) {
899             DatabaseEntry key = new DatabaseEntry();
900             DatabaseEntry pkey = new DatabaseEntry();
901             DatabaseEntry data = new DatabaseEntry();
902 
903             return MovePrev(key, pkey, data, info);
904         }
905         /// <summary>
906         /// If the cursor is not yet initialized, MovePrev is identical to
907         /// <see cref="MoveLast()"/>. Otherwise, move the cursor to the previous
908         /// key/data pair of the database, and store the secondary key and
909         /// primary key/data pair in <see cref="Current"/>. In the presence of
910         /// duplicate key values, the value of <see cref="Current">Current.Key
911         /// </see> may not change. If <paramref name="key"/>, or
912         /// <paramref name="pkey"/>, or <paramref name="data"/> is
913         /// partial <see cref="DatabaseEntry"/>, its
914         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
915         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
916         /// of the retrieved data record are returned as if they comprised the
917         /// entire record. If any or all of the specified bytes do not exist
918         /// in the record, MovePrev is successful, and any existing bytes are
919         /// returned.
920         /// </summary>
921         /// <remarks>
922         /// If positioning the cursor fails, <see cref="Current"/> will contain
923         /// an empty <see cref="KeyValuePair{T,T}"/>.
924         /// </remarks>
925         /// <param name="key">The retrieved key in secondary db</param>
926         /// <param name="pkey">
927         /// The key of the matching record in primary db
928         /// </param>
929         /// <param name="data">
930         /// The data of the matching record in primary db
931         /// </param>
932         /// <returns>
933         /// True if the cursor was positioned successfully, false otherwise.
934         /// </returns>
MovePrev( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)935         public bool MovePrev(
936             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
937             return MovePrev(key, pkey, data, null);
938         }
939         /// <summary>
940         /// If the cursor is not yet initialized, MovePrev is identical to
941         /// <see cref="MoveLast(LockingInfo)"/>. Otherwise, move the cursor to
942         /// the previous key/data pair of the database, and store the secondary
943         /// key and primary key/data pair in <see cref="Current"/>. In the
944         /// presence of duplicate key values, the value of <see cref="Current">
945         /// Current.Key</see> may not change. If <paramref name="key"/>, or
946         /// <paramref name="pkey"/>, or <paramref name="data"/> is
947         /// partial <see cref="DatabaseEntry"/>, its
948         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
949         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
950         /// of the retrieved data record are returned as if they comprised the
951         /// entire record. If any or all of the specified bytes do not exist
952         /// in the record, MovePrev is successful, and any existing bytes are
953         /// returned.
954         /// </summary>
955         /// <remarks>
956         /// If positioning the cursor fails, <see cref="Current"/> will contain
957         /// an empty <see cref="KeyValuePair{T,T}"/>.
958         /// </remarks>
959         /// <param name="key">The retrieved key in secondary db</param>
960         /// <param name="pkey">
961         /// The key of the matching record in primary db
962         /// </param>
963         /// <param name="data">
964         /// The data of the matching record in primary db
965         /// </param>
966         /// <param name="info">The locking behavior to use</param>
967         /// <returns>
968         /// True if the cursor was positioned successfully, false otherwise.
969         /// </returns>
MovePrev(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)970         public bool MovePrev(DatabaseEntry key, DatabaseEntry pkey,
971             DatabaseEntry data, LockingInfo info) {
972             return PGet(key, pkey, data, DbConstants.DB_PREV, info);
973         }
974 
975         /// <summary>
976         /// If the previous key/data pair of the database is a duplicate data
977         /// record for the current key/data pair, the cursor is moved to the
978         /// previous key/data pair of the database, and the secondary key and
979         /// primary key/data pair in <see cref="Current"/>. MovePrevDuplicate
980         /// will return false if the previous key/data pair of the database is
981         /// not a duplicate data record for the current key/data pair.
982         /// </summary>
983         /// <remarks>
984         /// If positioning the cursor fails, <see cref="Current"/> will contain
985         /// an empty <see cref="KeyValuePair{T,T}"/>.
986         /// </remarks>
987         /// <returns>
988         /// True if the cursor was positioned successfully, false otherwise.
989         /// </returns>
MovePrevDuplicate()990         public bool MovePrevDuplicate() { return MovePrevDuplicate(null); }
991         /// <summary>
992         /// If the previous key/data pair of the database is a duplicate data
993         /// record for the current key/data pair, the cursor is moved to the
994         /// previous key/data pair of the database, and the secondary key and
995         /// primary key/data pair in <see cref="Current"/>. MovePrevDuplicate
996         /// will return false if the previous key/data pair of the database is
997         /// not a duplicate data record for the current key/data pair.
998         /// </summary>
999         /// <remarks>
1000         /// If positioning the cursor fails, <see cref="Current"/> will contain
1001         /// an empty <see cref="KeyValuePair{T,T}"/>.
1002         /// </remarks>
1003         /// <param name="info">The locking behavior to use.</param>
1004         /// <returns>
1005         /// True if the cursor was positioned successfully, false otherwise.
1006         /// </returns>
MovePrevDuplicate(LockingInfo info)1007         public bool MovePrevDuplicate(LockingInfo info) {
1008             DatabaseEntry key = new DatabaseEntry();
1009             DatabaseEntry pkey = new DatabaseEntry();
1010             DatabaseEntry data = new DatabaseEntry();
1011 
1012             return MovePrevDuplicate(key, pkey, data, info);
1013         }
1014         /// <summary>
1015         /// If the previous key/data pair of the database is a duplicate data
1016         /// record for the current key/data pair, the cursor is moved to the
1017         /// previous key/data pair of the database, and the secondary key and
1018         /// primary key/data pair in <see cref="Current"/>. MovePrevDuplicate
1019         /// will return false if the previous key/data pair of the database is
1020         /// not a duplicate data record for the current key/data pair. If
1021         /// <paramref name="key"/>, or <paramref name="pkey"/>, or
1022         /// <paramref name="data"/> is partial <see cref="DatabaseEntry"/>, its
1023         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
1024         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
1025         /// of the retrieved data record are returned as if they comprised the
1026         /// entire record. If any or all of the specified bytes do not exist
1027         /// in the record, MovePrevDuplicate is successful, and any existing
1028         /// bytes are returned.
1029         /// </summary>
1030         /// <remarks>
1031         /// If positioning the cursor fails, <see cref="Current"/> will contain
1032         /// an empty <see cref="KeyValuePair{T,T}"/>.
1033         /// </remarks>
1034         /// <param name="key">The retrieved key in secondary db</param>
1035         /// <param name="pkey">
1036         /// The key of the matching record in primary db
1037         /// </param>
1038         /// <param name="data">
1039         /// The data of the matching record in primary db
1040         /// </param>
1041         /// <returns>
1042         /// True if the cursor was positioned successfully, false otherwise.
1043         /// </returns>
MovePrevDuplicate( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)1044         public bool MovePrevDuplicate(
1045             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
1046             return MovePrevDuplicate(key, pkey, data, null);
1047         }
1048         /// <summary>
1049         /// If the previous key/data pair of the database is a duplicate data
1050         /// record for the current key/data pair, the cursor is moved to the
1051         /// previous key/data pair of the database, and the secondary key and
1052         /// primary key/data pair in <see cref="Current"/>. MovePrevDuplicate
1053         /// will return false if the previous key/data pair of the database is
1054         /// not a duplicate data record for the current key/data pair. If
1055         /// <paramref name="key"/>, or <paramref name="pkey"/>, or
1056         /// <paramref name="data"/> is partial <see cref="DatabaseEntry"/>, its
1057         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
1058         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
1059         /// of the retrieved data record are returned as if they comprised the
1060         /// entire record. If any or all of the specified bytes do not exist
1061         /// in the record, MovePrevDuplicate is successful, and any existing
1062         /// bytes are returned.
1063         /// </summary>
1064         /// <remarks>
1065         /// If positioning the cursor fails, <see cref="Current"/> will contain
1066         /// an empty <see cref="KeyValuePair{T,T}"/>.
1067         /// </remarks>
1068         /// <param name="key">The retrieved key in secondary db</param>
1069         /// <param name="pkey">
1070         /// The key of the matching record in primary db
1071         /// </param>
1072         /// <param name="data">
1073         /// The data of the matching record in primary db
1074         /// </param>
1075         /// <param name="info">The locking behavior to use</param>
1076         /// <returns>
1077         /// True if the cursor was positioned successfully, false otherwise.
1078         /// </returns>
MovePrevDuplicate(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)1079         public bool MovePrevDuplicate(DatabaseEntry key, DatabaseEntry pkey,
1080             DatabaseEntry data, LockingInfo info) {
1081             return PGet(key, pkey, data, DbConstants.DB_PREV_DUP, info);
1082         }
1083 
1084         /// <summary>
1085         /// If the cursor is not yet initialized, MovePrevUnique is identical to
1086         /// <see cref="MoveLast()"/>. Otherwise, move the cursor to the previous
1087         /// non-duplicate key in the database, and store the secondary key and
1088         /// primary key/data pair in <see cref="Current"/>. MovePrevUnique will
1089         /// return false if no non-duplicate key/data pairs exist after the
1090         /// cursor position in the database.
1091         /// </summary>
1092         /// <remarks>
1093         /// If positioning the cursor fails, <see cref="Current"/> will contain
1094         /// an empty <see cref="KeyValuePair{T,T}"/>.
1095         /// </remarks>
1096         /// <returns>
1097         /// True if the cursor was positioned successfully, false otherwise.
1098         /// </returns>
MovePrevUnique()1099         public bool MovePrevUnique() { return MovePrevUnique(null); }
1100         /// <summary>
1101         /// If the cursor is not yet initialized, MovePrevUnique is identical to
1102         /// <see cref="MoveLast(LockingInfo)"/>. Otherwise, move the cursor to
1103         /// the previous non-duplicate key in the database, and store the
1104         /// secondary key and primary key/data pair in <see cref="Current"/>.
1105         /// MovePrevUnique will return false if no non-duplicate key/data pairs
1106         /// exist after the cursor position in the database.
1107         /// </summary>
1108         /// <remarks>
1109         /// If positioning the cursor fails, <see cref="Current"/> will contain
1110         /// an empty <see cref="KeyValuePair{T,T}"/>.
1111         /// </remarks>
1112         /// <param name="info">The locking behavior to use.</param>
1113         /// <returns>
1114         /// True if the cursor was positioned successfully, false otherwise.
1115         /// </returns>
MovePrevUnique(LockingInfo info)1116         public bool MovePrevUnique(LockingInfo info) {
1117             DatabaseEntry key = new DatabaseEntry();
1118             DatabaseEntry pkey = new DatabaseEntry();
1119             DatabaseEntry data = new DatabaseEntry();
1120 
1121             return MovePrevUnique(key, pkey, data, info);
1122         }
1123         /// <summary>
1124         /// If the cursor is not yet initialized, MovePrevUnique is identical to
1125         /// <see cref="MoveLast()"/>. Otherwise, move the cursor to the previous
1126         /// non-duplicate key in the database, and store the secondary key and
1127         /// primary key/data pair in <see cref="Current"/>. MovePrevUnique will
1128         /// return false if no non-duplicate key/data pairs exist after the
1129         /// cursor position in the database. If <paramref name="key"/>, or
1130         /// <paramref name="pkey"/>, or <paramref name="data"/> is
1131         /// partial <see cref="DatabaseEntry"/>, its
1132         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
1133         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
1134         /// of the retrieved data record are returned as if they comprised the
1135         /// entire record. If any or all of the specified bytes do not exist
1136         /// in the record, MovePrevUnique is successful, and any existing bytes
1137         /// are returned.
1138         /// </summary>
1139         /// <remarks>
1140         /// If positioning the cursor fails, <see cref="Current"/> will contain
1141         /// an empty <see cref="KeyValuePair{T,T}"/>.
1142         /// </remarks>
1143         /// <param name="key">The retrieved key in secondary db</param>
1144         /// <param name="pkey">
1145         /// The key of the matching record in primary db
1146         /// </param>
1147         /// <param name="data">
1148         /// The data of the matching record in primary db
1149         /// </param>
1150         /// <returns>
1151         /// True if the cursor was positioned successfully, false otherwise.
1152         /// </returns>
MovePrevUnique( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)1153         public bool MovePrevUnique(
1154             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
1155             return MovePrevUnique(key, pkey, data, null);
1156         }
1157         /// <summary>
1158         /// If the cursor is not yet initialized, MovePrevUnique is identical to
1159         /// <see cref="MoveLast(LockingInfo)"/>. Otherwise, move the cursor to
1160         /// the previous non-duplicate key in the database, and store the
1161         /// secondary key and primary key/data pair in <see cref="Current"/>.
1162         /// MovePrevUnique will return false if no non-duplicate key/data pairs
1163         /// exist after the cursor position in the database. If
1164         /// <paramref name="key"/>, or <paramref name="pkey"/>, or
1165         /// <paramref name="data"/> is partial <see cref="DatabaseEntry"/>, its
1166         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
1167         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
1168         /// of the retrieved data record are returned as if they comprised the
1169         /// entire record. If any or all of the specified bytes do not exist
1170         /// in the record, MovePrevUnique is successful, and any existing bytes
1171         /// are returned.
1172         /// </summary>
1173         /// <remarks>
1174         /// If positioning the cursor fails, <see cref="Current"/> will contain
1175         /// an empty <see cref="KeyValuePair{T,T}"/>.
1176         /// </remarks>
1177         /// <param name="key">The retrieved key in secondary db</param>
1178         /// <param name="pkey">
1179         /// The key of the matching record in primary db
1180         /// </param>
1181         /// <param name="data">
1182         /// The data of the matching record in primary db
1183         /// </param>
1184         /// <param name="info">The locking behavior to use</param>
1185         /// <returns>
1186         /// True if the cursor was positioned successfully, false otherwise.
1187         /// </returns>
MovePrevUnique(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)1188         public bool MovePrevUnique(DatabaseEntry key, DatabaseEntry pkey,
1189             DatabaseEntry data, LockingInfo info) {
1190             return PGet(key, pkey, data, DbConstants.DB_PREV_NODUP, info);
1191         }
1192 
1193         /// <summary>
1194         /// Store the secondary key and primary key/data pair to which the
1195         /// cursor refers in <see cref="Current"/>.
1196         /// </summary>
1197         /// <remarks>
1198         /// If positioning the cursor fails, <see cref="Current"/> will contain
1199         /// an empty <see cref="KeyValuePair{T,T}"/>.
1200         /// </remarks>
1201         /// <returns>
1202         /// True if the cursor was positioned successfully, false otherwise.
1203         /// </returns>
Refresh()1204         public bool Refresh() { return Refresh(null); }
1205         /// <summary>
1206         /// Store the secondary key and primary key/data pair to which the
1207         /// cursor refers in <see cref="Current"/>.
1208         /// </summary>
1209         /// <remarks>
1210         /// If positioning the cursor fails, <see cref="Current"/> will contain
1211         /// an empty <see cref="KeyValuePair{T,T}"/>.
1212         /// </remarks>
1213         /// <param name="info">The locking behavior to use.</param>
1214         /// <returns>
1215         /// True if the cursor was positioned successfully, false otherwise.
1216         /// </returns>
Refresh(LockingInfo info)1217         public bool Refresh(LockingInfo info) {
1218             DatabaseEntry key = new DatabaseEntry();
1219             DatabaseEntry pkey = new DatabaseEntry();
1220             DatabaseEntry data = new DatabaseEntry();
1221 
1222             return Refresh(key, pkey, data, info);
1223         }
1224         /// <summary>
1225         /// Store the secondary key and primary key/data pair to which the
1226         /// cursor refers in <see cref="Current"/>. If <paramref name="key"/>,
1227         /// or <paramref name="pkey"/>, or <paramref name="data"/> is
1228         /// partial <see cref="DatabaseEntry"/>, its
1229         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
1230         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
1231         /// of the retrieved data record are returned as if they comprised the
1232         /// entire record. If any or all of the specified bytes do not exist
1233         /// in the record, Refresh is successful, and any existing bytes are
1234         /// returned.
1235         /// </summary>
1236         /// <remarks>
1237         /// If positioning the cursor fails, <see cref="Current"/> will contain
1238         /// an empty <see cref="KeyValuePair{T,T}"/>.
1239         /// </remarks>
1240         /// <param name="key">The retrieved key in secondary db</param>
1241         /// <param name="pkey">
1242         /// The key of the matching record in primary db
1243         /// </param>
1244         /// <param name="data">
1245         /// The data of the matching record in primary db
1246         /// </param>
1247         /// <returns>
1248         /// True if the cursor was positioned successfully, false otherwise.
1249         /// </returns>
Refresh( DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data)1250         public bool Refresh(
1251             DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data) {
1252             return Refresh(key, pkey, data, null);
1253         }
1254         /// <summary>
1255         /// Store the secondary key and primary key/data pair to which the
1256         /// cursor refers in <see cref="Current"/>. If <paramref name="key"/>,
1257         /// or <paramref name="pkey"/>, or <paramref name="data"/> is
1258         /// partial <see cref="DatabaseEntry"/>, its
1259         /// <see cref="DatabaseEntry.PartialLen"/> bytes starting
1260         /// <see cref="DatabaseEntry.PartialOffset"/> bytes from the beginning
1261         /// of the retrieved data record are returned as if they comprised the
1262         /// entire record. If any or all of the specified bytes do not exist
1263         /// in the record, Refresh is successful, and any existing bytes are
1264         /// returned.
1265         /// </summary>
1266         /// <remarks>
1267         /// If positioning the cursor fails, <see cref="Current"/> will contain
1268         /// an empty <see cref="KeyValuePair{T,T}"/>.
1269         /// </remarks>
1270         /// <param name="key">The retrieved key in secondary db</param>
1271         /// <param name="pkey">
1272         /// The key of the matching record in primary db
1273         /// </param>
1274         /// <param name="data">
1275         /// The data of the matching record in primary db
1276         /// </param>
1277         /// <param name="info">The locking behavior to use</param>
1278         /// <returns>
1279         /// True if the cursor was positioned successfully, false otherwise.
1280         /// </returns>
Refresh(DatabaseEntry key, DatabaseEntry pkey, DatabaseEntry data, LockingInfo info)1281         public bool Refresh(DatabaseEntry key, DatabaseEntry pkey,
1282             DatabaseEntry data, LockingInfo info) {
1283             return PGet(key, pkey, data, DbConstants.DB_CURRENT, info);
1284         }
1285     }
1286 }
1287 
1288