/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2009 Oracle. All rights reserved. * */ using System; using System.Collections; using System.Collections.Generic; using System.Text; using BerkeleyDB.Internal; namespace BerkeleyDB { /// /// A class representing a join cursor, for use in performing equality or /// natural joins on secondary indices. For information on how to organize /// your data to use this functionality, see Equality join in the /// Programmer's Reference Guide. /// /// /// JoinCursor does not support many of the operations offered by /// and is not a subclass of . /// /// public class JoinCursor : IDisposable, IEnumerable> { internal DBC dbc; private bool isOpen; internal JoinCursor(DBC dbc) { this.dbc = dbc; isOpen = true; } /// /// /// Discard the cursor. /// /// /// It is possible for the Close() method to throw a /// , signaling that any enclosing /// transaction should be aborted. If the application is already /// intending to abort the transaction, this error should be ignored, /// and the application should proceed. /// /// /// After Close has been called, regardless of its result, the object /// may not be used again. /// /// /// public void Close() { isOpen = false; dbc.close(); } /// /// Release the resources held by this object, and close the cursor if /// it's still open. /// public void Dispose() { try { if (isOpen) Close(); } catch { /* * Errors here are likely because our dbc has been closed out * from under us. Not much we can do, just move on. */ } dbc.Dispose(); GC.SuppressFinalize(this); } private KeyValuePair cur; /// /// The key/data pair at which the cursor currently points. /// public KeyValuePair Current { get { return cur; } private set { cur = value; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Returns an enumerator that iterates through the /// . /// /// /// The enumerator will begin at the cursor's current position (or the /// first record if the cursor has not yet been positioned) and iterate /// forwards (i.e. in the direction of ) over the /// remaining records. /// /// An enumerator for the Cursor. public IEnumerator> GetEnumerator() { while (MoveNext()) yield return Current; } /// /// Iterate over the values associated with the keys to which each /// passed to /// was initialized. Any data value that appears in all /// s is then used as a key into the /// primary, and the key/data pair found in the primary is stored in /// . /// /// /// True if the cursor was positioned successfully, false otherwise. /// public bool MoveNext() { return MoveNext(null, false); } /// /// Iterate over the values associated with the keys to which each /// passed to /// was initialized. Any data value that appears in all /// s is then used as a key into the /// primary, and the key/data pair found in the primary is stored in /// . /// /// The locking behavior to use. /// /// True if the cursor was positioned successfully, false otherwise. /// public bool MoveNext(LockingInfo info) { return MoveNext(info, false); } /// /// Iterate over the values associated with the keys to which each /// passed to /// was initialized. Any data value that appears in all /// s is then stored in /// Current.Key. /// /// /// Current.Value will contain an empty /// . /// /// /// True if the cursor was positioned successfully, false otherwise. /// public bool MoveNextItem() { return MoveNext(null, true); } /// /// Iterate over the values associated with the keys to which each /// passed to /// was initialized. Any data value that appears in all /// s is then stored in /// Current.Key. /// /// /// Current.Value will contain an empty /// . /// /// The locking behavior to use. /// /// True if the cursor was positioned successfully, false otherwise. /// public bool MoveNextItem(LockingInfo info) { return MoveNext(info, true); } private bool MoveNext(LockingInfo info, bool joinItem) { int ret; uint flags = 0; DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); flags |= joinItem ? DbConstants.DB_JOIN_ITEM : 0; flags |= (info == null) ? 0 : info.flags; try { ret = dbc.get(key, data, flags); Current = new KeyValuePair(key, data); return true; } catch (NotFoundException) { Current = new KeyValuePair(); return false; } } } }