/*-
* 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;
}
}
}
}