To retrieve records in bulk, an application buffer must be specified to
the <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a> methods. This is done in the C API by setting
the <spanclass="bold"><strong>data</strong></span> and <spanclass="bold"><strong>ulen</strong></span> fields of the <spanclass="bold"><strong>data</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> to reference an application
buffer, and the
<spanclass="bold"><strong>flags</strong></span> field of that structure to
<ahref="../api_reference/C/dbt.html#dbt_DB_DBT_USERMEM"class="olink">DB_DBT_USERMEM</a>. In the Berkeley DB C++ and Java APIs, the actions
are similar, although there are API-specific methods to set the <ahref="../api_reference/C/dbt.html"class="olink">DBT</a>
values. Then, the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE"class="olink">DB_MULTIPLE</a> or <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE_KEY"class="olink">DB_MULTIPLE_KEY</a> flags are
specified to the <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a> methods, which cause multiple
records to be returned in the specified buffer.
</p>
<p>
The difference between <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE"class="olink">DB_MULTIPLE</a> and <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE_KEY"class="olink">DB_MULTIPLE_KEY</a> is as
follows: <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE"class="olink">DB_MULTIPLE</a> returns multiple data items for a single key.
For example, the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE"class="olink">DB_MULTIPLE</a> flag would be used to retrieve all of
the duplicate data items for a single key in a single call. The
<ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE_KEY"class="olink">DB_MULTIPLE_KEY</a> flag is used to retrieve multiple key/data pairs,
where each returned key may or may not have duplicate data items.
</p>
<p>
Once the <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a> method has returned, the application will
walk through the buffer handling the returned records. This is
implemented for the C and C++ APIs using four macros:
<ahref="../api_reference/C/DB_MULTIPLE_INIT.html"class="olink">DB_MULTIPLE_INIT</a>, <ahref="../api_reference/C/DB_MULTIPLE_NEXT.html"class="olink">DB_MULTIPLE_NEXT</a>, <ahref="../api_reference/C/DB_MULTIPLE_KEY_NEXT.html"class="olink">DB_MULTIPLE_KEY_NEXT</a>, and
<ahref="../api_reference/C/DB_MULTIPLE_RECNO_NEXT.html"class="olink">DB_MULTIPLE_RECNO_NEXT</a>. For the Java API, this is implemented as
and <aclass="ulink"href="../java/com/sleepycat/db/MultipleRecnoDataEntry.html"target="_top">MultipleRecnoDataEntry</a>.
</p>
<p>
The <ahref="../api_reference/C/DB_MULTIPLE_INIT.html"class="olink">DB_MULTIPLE_INIT</a> macro is always called first. It initializes a
local application variable and the <spanclass="bold"><strong>data</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> for stepping through the set of
returned records. Then, the application calls one of the remaining
three macros: <ahref="../api_reference/C/DB_MULTIPLE_NEXT.html"class="olink">DB_MULTIPLE_NEXT</a>, <ahref="../api_reference/C/DB_MULTIPLE_KEY_NEXT.html"class="olink">DB_MULTIPLE_KEY_NEXT</a>, and
If the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE"class="olink">DB_MULTIPLE</a> flag was specified to the <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a>
method, the application will always call the <ahref="../api_reference/C/DB_MULTIPLE_NEXT.html"class="olink">DB_MULTIPLE_NEXT</a> macro.
If the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE_KEY"class="olink">DB_MULTIPLE_KEY</a> flag was specified to the <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a>
method, and the underlying database is a Btree or Hash database, the
application will always call the <ahref="../api_reference/C/DB_MULTIPLE_KEY_NEXT.html"class="olink">DB_MULTIPLE_KEY_NEXT</a> macro. If the
<ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE_KEY"class="olink">DB_MULTIPLE_KEY</a> flag was specified to the <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a> method,
and the underlying database is a Queue or Recno database, the
application will always call the <ahref="../api_reference/C/DB_MULTIPLE_RECNO_NEXT.html"class="olink">DB_MULTIPLE_RECNO_NEXT</a> macro. The
<ahref="../api_reference/C/DB_MULTIPLE_NEXT.html"class="olink">DB_MULTIPLE_NEXT</a>, <ahref="../api_reference/C/DB_MULTIPLE_KEY_NEXT.html"class="olink">DB_MULTIPLE_KEY_NEXT</a>, and
<ahref="../api_reference/C/DB_MULTIPLE_RECNO_NEXT.html"class="olink">DB_MULTIPLE_RECNO_NEXT</a> macros are called repeatedly, until the end of
the returned records is reached. The end of the returned records is
detected by the application's local pointer variable being set to NULL.
</p>
<p>
Note that if you want to use a cursor for bulk retrieval of records in
a Btree database, you should open the cursor using the
<codeclass="literal">DB_CURSOR_BULK</code> flag. This optimizes the cursor for
bulk retrieval.
</p>
<p>
The following is an example of a routine that displays the contents of
a Btree database using the bulk return interfaces.
</p>
<aid="prog_am22"></a>
<preclass="programlisting">int
rec_display(DB *dbp)
{
DBC *dbcp;
DBT key, data;
size_t retklen, retdlen;
void *retkey, *retdata;
int ret, t_ret;
void *p;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* Review the database in 5MB chunks. */
#define BUFFER_LENGTH (5 * 1024 * 1024)
if ((data.data = malloc(BUFFER_LENGTH)) == NULL)
return (errno);
data.ulen = BUFFER_LENGTH;
data.flags = DB_DBT_USERMEM;
/* Acquire a cursor for the database. */
if ((ret = dbp->cursor(dbp, NULL, &dbcp, DB_CURSOR_BULK))
!= 0) {
dbp->err(dbp, ret, "DB->cursor");
free(data.data);
return (ret);
}
for (;;) {
/*
* Acquire the next set of key/data pairs. This code
* does not handle single key/data pairs that won't fit
* in a BUFFER_LENGTH size buffer, instead returning
<p>To put records in bulk with the btree or hash access methods, construct bulk buffers in the <spanclass="bold"><strong>key</strong></span> and <spanclass="bold"><strong>data</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_WRITE_INIT.html"class="olink">DB_MULTIPLE_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_WRITE_NEXT.html"class="olink">DB_MULTIPLE_WRITE_NEXT</a>. To put records in bulk with the recno or queue access methods, construct bulk buffers in the <spanclass="bold"><strong>data</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> as before, but construct the <spanclass="bold"><strong>key</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_INIT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_NEXT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_NEXT</a> with a data size of zero;. In both cases, set the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE"class="olink">DB_MULTIPLE</a> flag to <ahref="../api_reference/C/dbput.html"class="olink">DB->put()</a>.</p>
<p>Alternatively, for btree and hash access methods, construct a single bulk buffer in the <spanclass="bold"><strong>key</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_WRITE_INIT.html"class="olink">DB_MULTIPLE_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_KEY_WRITE_NEXT.html"class="olink">DB_MULTIPLE_KEY_WRITE_NEXT</a>. For recno and queue access methods, construct a bulk buffer in the <spanclass="bold"><strong>key</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_INIT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_NEXT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_NEXT</a>. In both cases, set the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE_KEY"class="olink">DB_MULTIPLE_KEY</a> flag to <ahref="../api_reference/C/dbput.html"class="olink">DB->put()</a>.
</p>
<p>A successful bulk operation is logically equivalent to a loop through each key/data pair, performing a <ahref="../api_reference/C/dbput.html"class="olink">DB->put()</a> for each one.</p>
<p>To delete all records with a specified set of keys with the btree or hash access methods, construct a bulk buffer in the <spanclass="bold"><strong>key</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_WRITE_INIT.html"class="olink">DB_MULTIPLE_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_WRITE_NEXT.html"class="olink">DB_MULTIPLE_WRITE_NEXT</a>. To delete a set of records with the recno or queue access methods, construct the <spanclass="bold"><strong>key</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_INIT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_NEXT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_NEXT</a> with a data size of zero. In both cases, set the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE"class="olink">DB_MULTIPLE</a> flag to <ahref="../api_reference/C/dbdel.html"class="olink">DB->del()</a>. This is equivalent to calling <ahref="../api_reference/C/dbdel.html"class="olink">DB->del()</a> for each key in the bulk buffer. In particular, if the database supports duplicates, all records with the matching key are deleted.</p>
<p>Alternatively, to delete a specific set of key/data pairs, which may be items within a set of duplicates, there are also two cases depending on whether the access method uses record numbers for keys. For btree and hash access methods, construct a single bulk buffer in the <spanclass="bold"><strong>key</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_WRITE_INIT.html"class="olink">DB_MULTIPLE_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_KEY_WRITE_NEXT.html"class="olink">DB_MULTIPLE_KEY_WRITE_NEXT</a>. For recno and queue access methods, construct a bulk buffer in the <spanclass="bold"><strong>key</strong></span><ahref="../api_reference/C/dbt.html"class="olink">DBT</a> using <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_INIT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_INIT</a> and <ahref="../api_reference/C/DB_MULTIPLE_RECNO_WRITE_NEXT.html"class="olink">DB_MULTIPLE_RECNO_WRITE_NEXT</a>. In both cases, set the <ahref="../api_reference/C/dbcget.html#dbcget_DB_MULTIPLE_KEY"class="olink">DB_MULTIPLE_KEY</a> flag to <ahref="../api_reference/C/dbdel.html"class="olink">DB->del()</a>.</p>
<p>A successful bulk operation is logically equivalent to a loop through each key/data pair, performing a <ahref="../api_reference/C/dbdel.html"class="olink">DB->del()</a> for each one.</p>