/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ package com.sleepycat.db; import com.sleepycat.db.internal.DbConstants; import com.sleepycat.db.internal.Dbc; /** A specialized join cursor for use in performing equality or natural joins on secondary indices. <p> A join cursor is returned when calling {@link Database#join Database.join}. <p> To open a join cursor using two secondary cursors: <pre> Transaction txn = ... Database primaryDb = ... SecondaryDatabase secondaryDb1 = ... SecondaryDatabase secondaryDb2 = ... <p> SecondaryCursor cursor1 = null; SecondaryCursor cursor2 = null; JoinCursor joinCursor = null; try { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); <p> cursor1 = secondaryDb1.openSecondaryCursor(txn, null); cursor2 = secondaryDb2.openSecondaryCursor(txn, null); <p> key.setData(...); // initialize key for secondary index 1 OperationStatus status1 = cursor1.getSearchKey(key, data, LockMode.DEFAULT); key.setData(...); // initialize key for secondary index 2 OperationStatus status2 = cursor2.getSearchKey(key, data, LockMode.DEFAULT); <p> if (status1 == OperationStatus.SUCCESS && status2 == OperationStatus.SUCCESS) { <p> SecondaryCursor[] cursors = {cursor1, cursor2}; joinCursor = primaryDb.join(cursors, null); <p> while (true) { OperationStatus joinStatus = joinCursor.getNext(key, data, LockMode.DEFAULT); if (joinStatus == OperationStatus.SUCCESS) { // Do something with the key and data. } else { break; } } } } finally { if (cursor1 != null) { cursor1.close(); } if (cursor2 != null) { cursor2.close(); } if (joinCursor != null) { joinCursor.close(); } } </pre> */ public class JoinCursor { private Database database; private Dbc dbc; private JoinConfig config; JoinCursor(final Database database, final Dbc dbc, final JoinConfig config) { this.database = database; this.dbc = dbc; this.config = config; } /** Closes the cursors that have been opened by this join cursor. <p> The cursors passed to {@link Database#join Database.join} are not closed by this method, and should be closed by the caller. <p> <p> @throws DatabaseException if a failure occurs. */ public void close() throws DatabaseException { dbc.close(); } /** Returns the primary database handle associated with this cursor. <p> @return the primary database handle associated with this cursor. */ public Database getDatabase() { return database; } /** Returns this object's configuration. <p> @return this object's configuration. */ public JoinConfig getConfig() { return config; } /** Returns the next primary key resulting from the join operation. <p> An entry is returned by the join cursor for each primary key/data pair having all secondary key values that were specified using the array of secondary cursors passed to {@link Database#join Database.join}. <p> @param key the primary key returned as output. Its byte array does not need to be initialized by the caller. <p> @return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. <p> @param lockMode the locking attributes; if null, default attributes are used. <p> @throws NullPointerException if a DatabaseEntry parameter is null or does not contain a required non-null byte array. <p> @throws DeadlockException if the operation was selected to resolve a deadlock. <p> @throws IllegalArgumentException if an invalid parameter was specified. <p> @throws DatabaseException if a failure occurs. */ public OperationStatus getNext(final DatabaseEntry key, LockMode lockMode) throws DatabaseException { return OperationStatus.fromInt( dbc.get(key, DatabaseEntry.IGNORE, DbConstants.DB_JOIN_ITEM | LockMode.getFlag(lockMode))); } /** Returns the next primary key and data resulting from the join operation. <p> An entry is returned by the join cursor for each primary key/data pair having all secondary key values that were specified using the array of secondary cursors passed to {@link Database#join Database.join}. <p> @param key the primary key returned as output. Its byte array does not need to be initialized by the caller. <p> @param data the primary data returned as output. Its byte array does not need to be initialized by the caller. <p> @return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. <p> @param lockMode the locking attributes; if null, default attributes are used. <p> @throws NullPointerException if a DatabaseEntry parameter is null or does not contain a required non-null byte array. <p> @throws DeadlockException if the operation was selected to resolve a deadlock. <p> @throws IllegalArgumentException if an invalid parameter was specified. <p> @throws DatabaseException if a failure occurs. */ public OperationStatus getNext(final DatabaseEntry key, final DatabaseEntry data, LockMode lockMode) throws DatabaseException { return OperationStatus.fromInt( dbc.get(key, data, LockMode.getFlag(lockMode) | ((data == null) ? 0 : data.getMultiFlag()))); } }