• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/db-4.8.30/docs/programmer_reference/
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
4  <head>
5    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6    <title>Cursor operations</title>
7    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
8    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
9    <link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
10    <link rel="up" href="am.html" title="Chapter��3.�� Access Method Operations" />
11    <link rel="prev" href="am_foreign.html" title="Foreign key indexes" />
12    <link rel="next" href="am_misc.html" title="Chapter��4.�� Access Method Wrapup" />
13  </head>
14  <body>
15    <div class="navheader">
16      <table width="100%" summary="Navigation header">
17        <tr>
18          <th colspan="3" align="center">Cursor operations</th>
19        </tr>
20        <tr>
21          <td width="20%" align="left"><a accesskey="p" href="am_foreign.html">Prev</a>��</td>
22          <th width="60%" align="center">Chapter��3.��
23		Access Method Operations
24        </th>
25          <td width="20%" align="right">��<a accesskey="n" href="am_misc.html">Next</a></td>
26        </tr>
27      </table>
28      <hr />
29    </div>
30    <div class="sect1" lang="en" xml:lang="en">
31      <div class="titlepage">
32        <div>
33          <div>
34            <h2 class="title" style="clear: both"><a id="am_cursor"></a>Cursor operations</h2>
35          </div>
36        </div>
37      </div>
38      <div class="toc">
39        <dl>
40          <dt>
41            <span class="sect2">
42              <a href="am_cursor.html#am_curget">Retrieving records with a cursor</a>
43            </span>
44          </dt>
45          <dt>
46            <span class="sect2">
47              <a href="am_cursor.html#am_curput">Storing records with a cursor</a>
48            </span>
49          </dt>
50          <dt>
51            <span class="sect2">
52              <a href="am_cursor.html#am_curdel">Deleting records with a cursor</a>
53            </span>
54          </dt>
55          <dt>
56            <span class="sect2">
57              <a href="am_cursor.html#am_curdup">Duplicating a cursor</a>
58            </span>
59          </dt>
60          <dt>
61            <span class="sect2">
62              <a href="am_cursor.html#am_join">Equality Join</a>
63            </span>
64          </dt>
65          <dt>
66            <span class="sect2">
67              <a href="am_cursor.html#am_count">Data item count</a>
68            </span>
69          </dt>
70          <dt>
71            <span class="sect2">
72              <a href="am_cursor.html#am_curclose">Cursor close</a>
73            </span>
74          </dt>
75        </dl>
76      </div>
77      <p>A database cursor refers to a single key/data pair in the database.  It
78supports traversal of the database and is the only way to access
79individual duplicate data items.  Cursors are used for operating on
80collections of records, for iterating over a database, and for saving
81handles to individual records, so that they can be modified after they
82have been read.</p>
83      <p>The <a href="../api_reference/C/dbcursor.html" class="olink">DB-&gt;cursor()</a> method opens a cursor into a database.  Upon return the
84cursor is uninitialized, cursor positioning occurs as part of the first
85cursor operation.</p>
86      <p>Once a database cursor has been opened, records may be retrieved
87(<a href="../api_reference/C/dbcget.html" class="olink">DBC-&gt;get()</a>), stored (<a href="../api_reference/C/dbcput.html" class="olink">DBC-&gt;put()</a>), and deleted (<a href="../api_reference/C/dbcdel.html" class="olink">DBC-&gt;del()</a>).</p>
88      <p>Additional operations supported by the cursor handle include duplication
89(<a href="../api_reference/C/dbcdup.html" class="olink">DBC-&gt;dup()</a>), equality join (<a href="../api_reference/C/dbjoin.html" class="olink">DB-&gt;join()</a>), and a count of
90duplicate data items (<a href="../api_reference/C/dbccount.html" class="olink">DBC-&gt;count()</a>).  Cursors are eventually closed
91using <a href="../api_reference/C/dbcclose.html" class="olink">DBC-&gt;close()</a>.</p>
92      <div class="informaltable">
93        <table border="1" width="80%">
94          <colgroup>
95            <col />
96            <col />
97          </colgroup>
98          <thead>
99            <tr>
100              <th>Database Cursors and Related Methods</th>
101              <th>Description</th>
102            </tr>
103          </thead>
104          <tbody>
105            <tr>
106              <td>
107                <a href="../api_reference/C/dbcursor.html" class="olink">DB-&gt;cursor()</a>
108              </td>
109              <td>Create a cursor</td>
110            </tr>
111            <tr>
112              <td>
113                <a href="../api_reference/C/dbcclose.html" class="olink">DBC-&gt;close()</a>
114              </td>
115              <td>Close a cursor</td>
116            </tr>
117            <tr>
118              <td>
119                <a href="../api_reference/C/dbccount.html" class="olink">DBC-&gt;count()</a>
120              </td>
121              <td>Return count of duplicates</td>
122            </tr>
123            <tr>
124              <td>
125                <a href="../api_reference/C/dbcdel.html" class="olink">DBC-&gt;del()</a>
126              </td>
127              <td>Delete by cursor</td>
128            </tr>
129            <tr>
130              <td>
131                <a href="../api_reference/C/dbcdup.html" class="olink">DBC-&gt;dup()</a>
132              </td>
133              <td>Duplicate a cursor</td>
134            </tr>
135            <tr>
136              <td>
137                <a href="../api_reference/C/dbcget.html" class="olink">DBC-&gt;get()</a>
138              </td>
139              <td>Retrieve by cursor</td>
140            </tr>
141            <tr>
142              <td>
143                <a href="../api_reference/C/dbcput.html" class="olink">DBC-&gt;put()</a>
144              </td>
145              <td>Store by cursor</td>
146            </tr>
147            <tr>
148              <td>
149                <a href="../api_reference/C/dbcset_priority.html" class="olink">DBC-&gt;set_priority()</a>
150              </td>
151              <td>Set the cursor's cache priority</td>
152            </tr>
153          </tbody>
154        </table>
155      </div>
156      <div class="sect2" lang="en" xml:lang="en">
157        <div class="titlepage">
158          <div>
159            <div>
160              <h3 class="title"><a id="am_curget"></a>Retrieving records with a cursor</h3>
161            </div>
162          </div>
163        </div>
164        <p>The <a href="../api_reference/C/dbcget.html" class="olink">DBC-&gt;get()</a> method retrieves records from the database using a cursor.
165The <a href="../api_reference/C/dbcget.html" class="olink">DBC-&gt;get()</a> method takes a flag which controls how the cursor is
166positioned within the database and returns the key/data item associated
167with that positioning.  Similar to <a href="../api_reference/C/dbget.html" class="olink">DB-&gt;get()</a>, <a href="../api_reference/C/dbcget.html" class="olink">DBC-&gt;get()</a> may
168also take a supplied key and retrieve the data associated with that key
169from the database.  There are several flags that you can set to
170customize retrieval.</p>
171        <div class="sect3" lang="en" xml:lang="en">
172          <div class="titlepage">
173            <div>
174              <div>
175                <h4 class="title"><a id="id1594258"></a>Cursor position flags</h4>
176              </div>
177            </div>
178          </div>
179          <div class="variablelist">
180            <dl>
181              <dt>
182                <span class="term"><a href="../api_reference/C/dbcget.html#dbcget_DB_FIRST" class="olink">DB_FIRST</a>, <a href="../api_reference/C/dbcget.html#dbcget_DB_LAST" class="olink">DB_LAST</a></span>
183              </dt>
184              <dd>Return the first (last) record in the database.</dd>
185              <dt>
186                <span class="term"><a href="../api_reference/C/dbcget.html#dbcget_DB_NEXT" class="olink">DB_NEXT</a>, <a href="../api_reference/C/dbcget.html#dbcget_DB_PREV" class="olink">DB_PREV</a></span>
187              </dt>
188              <dd>Return the next (previous) record in the database.</dd>
189              <dt>
190                <span class="term">
191                  <a href="../api_reference/C/dbcget.html#dbcget_DB_NEXT_DUP" class="olink">DB_NEXT_DUP</a>
192                </span>
193              </dt>
194              <dd>Return the next record in the database, if it is a duplicate data item
195for the current key.</dd>
196              <dt>
197                <span class="term"><a href="../api_reference/C/dbcget.html#dbcget_DB_NEXT_NODUP" class="olink">DB_NEXT_NODUP</a>, <a href="../api_reference/C/dbcget.html#dbcget_DB_PREV_NODUP" class="olink">DB_PREV_NODUP</a></span>
198              </dt>
199              <dd>Return the next (previous) record in the database that is not a
200duplicate data item for the current key.</dd>
201              <dt>
202                <span class="term">
203                  <a href="../api_reference/C/dbcget.html#dbcget_DB_CURRENT" class="olink">DB_CURRENT</a>
204                </span>
205              </dt>
206              <dd>Return the record from the database to which the cursor currently refers.</dd>
207            </dl>
208          </div>
209        </div>
210        <div class="sect3" lang="en" xml:lang="en">
211          <div class="titlepage">
212            <div>
213              <div>
214                <h4 class="title"><a id="id1594936"></a>Retrieving specific key/data pairs</h4>
215              </div>
216            </div>
217          </div>
218          <div class="variablelist">
219            <dl>
220              <dt>
221                <span class="term">
222                  <a href="../api_reference/C/dbcget.html#dbcget_DB_SET" class="olink">DB_SET</a>
223                </span>
224              </dt>
225              <dd>Return the record from the database that matches the supplied key.  In
226the case of duplicates the first duplicate is returned and the cursor
227is positioned at the beginning of the duplicate list.  The user can then
228traverse the duplicate entries for the key.</dd>
229              <dt>
230                <span class="term">
231                  <a href="../api_reference/C/dbcget.html#dbcget_DB_SET_RANGE" class="olink">DB_SET_RANGE</a>
232                </span>
233              </dt>
234              <dd>Return the smallest record in the database greater than or equal to the
235supplied key.  This functionality permits partial key matches and range
236searches in the Btree access method.</dd>
237              <dt>
238                <span class="term">
239                  <a href="../api_reference/C/dbcget.html#dbcget_DB_GET_BOTH" class="olink">DB_GET_BOTH</a>
240                </span>
241              </dt>
242              <dd>Return the record from the database that matches both the supplied key
243and data items.  This is particularly useful when there are large
244numbers of duplicate records for a key, as it allows the cursor to
245easily be positioned at the correct place for traversal of some part of
246a large set of duplicate records.</dd>
247              <dt>
248                <span class="term">
249                  <a href="../api_reference/C/dbcget.html#dbcget_DB_GET_BOTH_RANGE" class="olink">DB_GET_BOTH_RANGE</a>
250                </span>
251              </dt>
252              <dd>Return the smallest record in the database greater than or equal to the
253supplied key and data items.</dd>
254            </dl>
255          </div>
256        </div>
257        <div class="sect3" lang="en" xml:lang="en">
258          <div class="titlepage">
259            <div>
260              <div>
261                <h4 class="title"><a id="id1594955"></a>Retrieving based on record numbers</h4>
262              </div>
263            </div>
264          </div>
265          <div class="variablelist">
266            <dl>
267              <dt>
268                <span class="term">
269                  <a href="../api_reference/C/dbcget.html#dbcget_DB_SET_RECNO" class="olink">DB_SET_RECNO</a>
270                </span>
271              </dt>
272              <dd>If the underlying database is a Btree, and was configured so that it is
273possible to search it by logical record number, retrieve a specific
274record based on a record number argument.</dd>
275              <dt>
276                <span class="term">
277                  <a href="../api_reference/C/dbcget.html#dbcget_DB_GET_RECNO" class="olink">DB_GET_RECNO</a>
278                </span>
279              </dt>
280              <dd>If the underlying database is a Btree, and was configured so that it is
281possible to search it by logical record number, return the record number
282for the record to which the cursor refers.</dd>
283            </dl>
284          </div>
285        </div>
286        <div class="sect3" lang="en" xml:lang="en">
287          <div class="titlepage">
288            <div>
289              <div>
290                <h4 class="title"><a id="id1595030"></a>Special-purpose flags</h4>
291              </div>
292            </div>
293          </div>
294          <div class="variablelist">
295            <dl>
296              <dt>
297                <span class="term">
298                  <a href="../api_reference/C/dbget.html#dbget_DB_CONSUME" class="olink">DB_CONSUME</a>
299                </span>
300              </dt>
301              <dd>Read-and-delete: the first record (the head) of the queue is returned and
302deleted.  The underlying database must be a Queue.</dd>
303              <dt>
304                <span class="term">
305                  <a href="../api_reference/C/dbcget.html#dbcget_DB_RMW" class="olink">DB_RMW</a>
306                </span>
307              </dt>
308              <dd>Read-modify-write: acquire write locks instead of read locks during
309retrieval. This can enhance performance in threaded applications by
310reducing the chance of deadlock.</dd>
311            </dl>
312          </div>
313          <p>In all cases, the cursor is repositioned by a <a href="../api_reference/C/dbcget.html" class="olink">DBC-&gt;get()</a> operation
314to point to the newly-returned key/data pair in the database.</p>
315          <p>The following is a code example showing a cursor walking through a
316database and displaying the records it contains to the standard
317output:</p>
318          <pre class="programlisting">int
319display(database)
320	char *database;
321{
322	DB *dbp;
323	DBC *dbcp;
324	DBT key, data;
325	int close_db, close_dbc, ret;
326
327	close_db = close_dbc = 0;
328
329	/* Open the database. */
330	if ((ret = db_create(&amp;dbp, NULL, 0)) != 0) {
331		fprintf(stderr,
332		    "%s: db_create: %s\n", progname, db_strerror(ret));
333		return (1);
334	}
335	close_db = 1;
336
337	/* Turn on additional error output. */
338	dbp-&gt;set_errfile(dbp, stderr);
339	dbp-&gt;set_errpfx(dbp, progname);
340
341	/* Open the database. */
342	if ((ret = dbp-&gt;open(dbp, NULL, database, NULL, 
343            DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
344		dbp-&gt;err(dbp, ret, "%s: DB-&gt;open", database);
345		goto err;
346	}
347
348	/* Acquire a cursor for the database. */
349	if ((ret = dbp-&gt;cursor(dbp, NULL, &amp;dbcp, 0)) != 0) {
350		dbp-&gt;err(dbp, ret, "DB-&gt;cursor");
351		goto err;
352	}
353	close_dbc = 1;
354
355	/* Initialize the key/data return pair. */
356	memset(&amp;key, 0, sizeof(key));
357	memset(&amp;data, 0, sizeof(data));
358
359	/* Walk through the database and print out the key/data pairs. */
360	while ((ret = dbcp-&gt;c_get(dbcp, &amp;key, &amp;data, DB_NEXT)) == 0)
361		printf("%.*s : %.*s\n",
362		    (int)key.size, (char *)key.data,
363		    (int)data.size, (char *)data.data);
364	if (ret != DB_NOTFOUND) {
365		dbp-&gt;err(dbp, ret, "DBcursor-&gt;get");
366		goto err;
367	}
368
369err:	if (close_dbc &amp;&amp; (ret = dbcp-&gt;c_close(dbcp)) != 0)
370		dbp-&gt;err(dbp, ret, "DBcursor-&gt;close");
371	if (close_db &amp;&amp; (ret = dbp-&gt;close(dbp, 0)) != 0)
372		fprintf(stderr,
373		    "%s: DB-&gt;close: %s\n", progname, db_strerror(ret));
374	return (0);
375}</pre>
376        </div>
377      </div>
378      <div class="sect2" lang="en" xml:lang="en">
379        <div class="titlepage">
380          <div>
381            <div>
382              <h3 class="title"><a id="am_curput"></a>Storing records with a cursor</h3>
383            </div>
384          </div>
385        </div>
386        <p>The <a href="../api_reference/C/dbcput.html" class="olink">DBC-&gt;put()</a> method stores records into the database using a cursor.  In
387general, <a href="../api_reference/C/dbcput.html" class="olink">DBC-&gt;put()</a> takes a key and inserts the associated data
388into the database, at a location controlled by a specified flag.</p>
389        <p>There are several flags that you can set to customize storage:</p>
390        <div class="variablelist">
391          <dl>
392            <dt>
393              <span class="term">
394                <a href="../api_reference/C/dbcput.html#put_DB_AFTER" class="olink">DB_AFTER</a>
395              </span>
396            </dt>
397            <dd>Create a new record, immediately after the record to which the cursor
398refers.</dd>
399            <dt>
400              <span class="term">
401                <a href="../api_reference/C/dbcput.html#put_DB_BEFORE" class="olink">DB_BEFORE</a>
402              </span>
403            </dt>
404            <dd>Create a new record, immediately before the record to which the cursor
405refers.</dd>
406            <dt>
407              <span class="term">
408                <a href="../api_reference/C/dbcget.html#dbcget_DB_CURRENT" class="olink">DB_CURRENT</a>
409              </span>
410            </dt>
411            <dd>Replace the data part of the record to which the cursor refers.</dd>
412            <dt>
413              <span class="term">
414                <a href="../api_reference/C/dbcput.html#put_DB_KEYFIRST" class="olink">DB_KEYFIRST</a>
415              </span>
416            </dt>
417            <dd>Create a new record as the first of the duplicate records for the
418supplied key.</dd>
419            <dt>
420              <span class="term">
421                <a href="../api_reference/C/dbcput.html#put_DB_KEYLAST" class="olink">DB_KEYLAST</a>
422              </span>
423            </dt>
424            <dd>Create a new record, as the last of the duplicate records for the supplied
425key.</dd>
426          </dl>
427        </div>
428        <p>In all cases, the cursor is repositioned by a <a href="../api_reference/C/dbcput.html" class="olink">DBC-&gt;put()</a> operation
429to point to the newly inserted key/data pair in the database.</p>
430        <p>The following is a code example showing a cursor storing two data items
431in a database that supports duplicate data items:</p>
432        <pre class="programlisting">int
433store(dbp)
434	DB *dbp;
435{
436	DBC *dbcp;
437	DBT key, data;
438	int ret;
439
440	/*
441	 * The DB handle for a Btree database supporting duplicate data
442	 * items is the argument; acquire a cursor for the database.
443	 */
444	if ((ret = dbp-&gt;cursor(dbp, NULL, &amp;dbcp, 0)) != 0) {
445		dbp-&gt;err(dbp, ret, "DB-&gt;cursor");
446		goto err;
447	}
448
449	/* Initialize the key. */
450	memset(&amp;key, 0, sizeof(key));
451	key.data = "new key";
452	key.size = strlen(key.data) + 1;
453
454	/* Initialize the data to be the first of two duplicate records. */
455	memset(&amp;data, 0, sizeof(data));
456	data.data = "new key's data: entry #1";
457	data.size = strlen(data.data) + 1;
458
459	/* Store the first of the two duplicate records. */
460	if ((ret = dbcp-&gt;c_put(dbcp, &amp;key, &amp;data, DB_KEYFIRST)) != 0)
461		dbp-&gt;err(dbp, ret, "DB-&gt;cursor");
462
463	/* Initialize the data to be the second of two duplicate records. */
464	data.data = "new key's data: entry #2";
465	data.size = strlen(data.data) + 1;
466
467	/*
468	 * Store the second of the two duplicate records.  No duplicate
469	 * record sort function has been specified, so we explicitly
470	 * store the record as the last of the duplicate set.
471	 */
472	if ((ret = dbcp-&gt;c_put(dbcp, &amp;key, &amp;data, DB_KEYLAST)) != 0)
473		dbp-&gt;err(dbp, ret, "DB-&gt;cursor");
474
475err:	if ((ret = dbcp-&gt;c_close(dbcp)) != 0)
476		dbp-&gt;err(dbp, ret, "DBcursor-&gt;close");
477
478	return (0);
479}</pre>
480      </div>
481      <div class="sect2" lang="en" xml:lang="en">
482        <div class="titlepage">
483          <div>
484            <div>
485              <h3 class="title"><a id="am_curdel"></a>Deleting records with a cursor</h3>
486            </div>
487          </div>
488        </div>
489        <p>The <a href="../api_reference/C/dbcdel.html" class="olink">DBC-&gt;del()</a> method deletes records from the database using a cursor.
490The <a href="../api_reference/C/dbcdel.html" class="olink">DBC-&gt;del()</a> method deletes the record to which the cursor currently
491refers.  In all cases, the cursor position is unchanged after a
492delete.</p>
493      </div>
494      <div class="sect2" lang="en" xml:lang="en">
495        <div class="titlepage">
496          <div>
497            <div>
498              <h3 class="title"><a id="am_curdup"></a>Duplicating a cursor</h3>
499            </div>
500          </div>
501        </div>
502        <p>Once a cursor has been initialized (for example, by a call to
503<a href="../api_reference/C/dbcget.html" class="olink">DBC-&gt;get()</a>), it can be thought of as identifying a particular
504location in a database.  The <a href="../api_reference/C/dbcdup.html" class="olink">DBC-&gt;dup()</a> method permits an application to
505create a new cursor that has the same locking and transactional
506information as the cursor from which it is copied, and which optionally
507refers to the same position in the database.</p>
508        <p>In order to maintain a cursor position when an application is using
509locking, locks are maintained on behalf of the cursor until the cursor is
510closed.  In cases when an application is using locking without
511transactions, cursor duplication is often required to avoid
512self-deadlocks.  For further details, refer to
513<a class="xref" href="lock_am_conv.html" title="Berkeley DB Transactional Data Store locking conventions">Berkeley DB Transactional Data Store locking conventions</a>.</p>
514      </div>
515      <div class="sect2" lang="en" xml:lang="en">
516        <div class="titlepage">
517          <div>
518            <div>
519              <h3 class="title"><a id="am_join"></a>Equality Join</h3>
520            </div>
521          </div>
522        </div>
523        <p>Berkeley DB supports "equality" (also known as "natural"), joins on secondary
524indices.  An equality join is a method of retrieving data from a primary
525database using criteria stored in a set of secondary indices.  It
526requires the data be organized as a primary database which contains the
527primary key and primary data field, and a set of secondary indices.
528Each of the secondary indices is indexed by a different secondary key,
529and, for each key in a secondary index, there is a set of duplicate data
530items that match the primary keys in the primary database.</p>
531        <p>For example, let's assume the need for an application that will return
532the names of stores in which one can buy fruit of a given color.  We
533would first construct a primary database that lists types of fruit as
534the key item, and the store where you can buy them as the data item:</p>
535        <div class="informaltable">
536          <table border="1" width="80%">
537            <colgroup>
538              <col />
539              <col />
540            </colgroup>
541            <thead>
542              <tr>
543                <th>Primary key:</th>
544                <th>Primary data:</th>
545              </tr>
546            </thead>
547            <tbody>
548              <tr>
549                <td align="left">apple</td>
550                <td align="left">Convenience Store</td>
551              </tr>
552              <tr>
553                <td align="left">blueberry</td>
554                <td align="left">Farmer's Market</td>
555              </tr>
556              <tr>
557                <td align="left">peach</td>
558                <td align="left">Shopway</td>
559              </tr>
560              <tr>
561                <td align="left">pear</td>
562                <td align="left">Farmer's Market</td>
563              </tr>
564              <tr>
565                <td align="left">raspberry</td>
566                <td align="left">Shopway</td>
567              </tr>
568              <tr>
569                <td align="left">strawberry</td>
570                <td align="left">Farmer's Market</td>
571              </tr>
572            </tbody>
573          </table>
574        </div>
575        <p>We would then create a secondary index with the key <span class="bold"><strong>color</strong></span>, and,
576as the data items, the names of fruits of different colors.</p>
577        <div class="informaltable">
578          <table border="1" width="80%">
579            <colgroup>
580              <col />
581              <col />
582            </colgroup>
583            <thead>
584              <tr>
585                <th>Secondary key:</th>
586                <th>Secondary data:</th>
587              </tr>
588            </thead>
589            <tbody>
590              <tr>
591                <td align="left">blue</td>
592                <td align="left">blueberry</td>
593              </tr>
594              <tr>
595                <td align="left">red</td>
596                <td align="left">apple</td>
597              </tr>
598              <tr>
599                <td align="left">red</td>
600                <td align="left">raspberry</td>
601              </tr>
602              <tr>
603                <td align="left">red</td>
604                <td align="left">strawberry</td>
605              </tr>
606              <tr>
607                <td align="left">yellow</td>
608                <td align="left">peach</td>
609              </tr>
610              <tr>
611                <td align="left">yellow</td>
612                <td align="left">pear</td>
613              </tr>
614            </tbody>
615          </table>
616        </div>
617        <p>This secondary index would allow an application to look up a color, and
618then use the data items to look up the stores where the colored fruit
619could be purchased.  For example, by first looking up <span class="bold"><strong>blue</strong></span>,
620the data item <span class="bold"><strong>blueberry</strong></span> could be used as the lookup key in the
621primary database, returning <span class="bold"><strong>Farmer's Market</strong></span>.</p>
622        <p>Your data must be organized in the following manner in order to use the
623<a href="../api_reference/C/dbjoin.html" class="olink">DB-&gt;join()</a> method:</p>
624        <div class="orderedlist">
625          <ol type="1">
626            <li>The actual data should be stored in the database represented by the
627<a href="../api_reference/C/db.html" class="olink">DB</a> object used to invoke this method.  Generally, this
628<a href="../api_reference/C/db.html" class="olink">DB</a> object is called the <span class="emphasis"><em>primary</em></span>.</li>
629            <li>Secondary indices should be stored in separate databases, whose keys
630are the values of the secondary indices and whose data items are the
631primary keys corresponding to the records having the designated
632secondary key value.  It is acceptable (and expected) that there may be
633duplicate entries in the secondary indices.
634<p>These duplicate entries should be sorted for performance reasons, although
635it is not required.  For more information see the <a href="../api_reference/C/dbset_flags.html#dbset_flags_DB_DUPSORT" class="olink">DB_DUPSORT</a> flag
636to the <a href="../api_reference/C/dbset_flags.html" class="olink">DB-&gt;set_flags()</a> method.</p></li>
637          </ol>
638        </div>
639        <p>What the <a href="../api_reference/C/dbjoin.html" class="olink">DB-&gt;join()</a> method does is review a list of secondary keys, and,
640when it finds a data item that appears as a data item for all of the
641secondary keys, it uses that data item as a lookup into the primary
642database, and returns the associated data item.</p>
643        <p>If there were another secondary index that had as its key the <span class="bold"><strong>cost</strong></span>
644of the fruit, a similar lookup could be done on stores where inexpensive
645fruit could be purchased:</p>
646        <div class="informaltable">
647          <table border="1" width="80%">
648            <colgroup>
649              <col />
650              <col />
651            </colgroup>
652            <thead>
653              <tr>
654                <th>Secondary key:</th>
655                <th>Secondary data:</th>
656              </tr>
657            </thead>
658            <tbody>
659              <tr>
660                <td align="left">expensive</td>
661                <td align="left">blueberry</td>
662              </tr>
663              <tr>
664                <td align="left">expensive</td>
665                <td align="left">peach</td>
666              </tr>
667              <tr>
668                <td align="left">expensive</td>
669                <td align="left">pear</td>
670              </tr>
671              <tr>
672                <td align="left">expensive</td>
673                <td align="left">strawberry</td>
674              </tr>
675              <tr>
676                <td align="left">inexpensive</td>
677                <td align="left">apple</td>
678              </tr>
679              <tr>
680                <td align="left">inexpensive</td>
681                <td align="left">pear</td>
682              </tr>
683              <tr>
684                <td align="left">inexpensive</td>
685                <td align="left">raspberry</td>
686              </tr>
687            </tbody>
688          </table>
689        </div>
690        <p>The <a href="../api_reference/C/dbjoin.html" class="olink">DB-&gt;join()</a> method provides equality join functionality.  While not
691strictly cursor functionality, in that it is not a method off a cursor
692handle, it is more closely related to the cursor operations than to the
693standard <a href="../api_reference/C/db.html" class="olink">DB</a> operations.</p>
694        <p>It is also possible to do lookups based on multiple criteria in a single
695operation.  For example, it is possible to look up fruits that are both
696red and expensive in a single operation.  If the same fruit appeared as
697a data item in both the color and expense indices, then that fruit name
698would be used as the key for retrieval from the primary index, and would
699then return the store where expensive, red fruit could be purchased.</p>
700        <div class="sect3" lang="en" xml:lang="en">
701          <div class="titlepage">
702            <div>
703              <div>
704                <h4 class="title"><a id="id1595662"></a>Example</h4>
705              </div>
706            </div>
707          </div>
708          <p>Consider the following three databases:</p>
709          <div class="variablelist">
710            <dl>
711              <dt>
712                <span class="term">personnel</span>
713              </dt>
714              <dd>
715                <div class="itemizedlist">
716                  <ul type="disc">
717                    <li>key = SSN</li>
718                    <li>data = record containing name, address, phone number, job title</li>
719                  </ul>
720                </div>
721              </dd>
722              <dt>
723                <span class="term">lastname</span>
724              </dt>
725              <dd>
726                <div class="itemizedlist">
727                  <ul type="disc">
728                    <li>key = lastname</li>
729                    <li>data = SSN</li>
730                  </ul>
731                </div>
732              </dd>
733              <dt>
734                <span class="term">jobs</span>
735              </dt>
736              <dd>
737                <div class="itemizedlist">
738                  <ul type="disc">
739                    <li>key = job title</li>
740                    <li>data = SSN</li>
741                  </ul>
742                </div>
743              </dd>
744            </dl>
745          </div>
746          <p>Consider the following query:</p>
747          <pre class="programlisting">Return the personnel records of all people named smith with the job
748title manager.</pre>
749          <p>This query finds are all the records in the primary database (personnel)
750for whom the criteria <span class="bold"><strong>lastname=smith and job title=manager</strong></span> is
751true.</p>
752          <p>Assume that all databases have been properly opened and have the
753handles:  pers_db, name_db, job_db.  We also assume that we have an
754active transaction to which the handle txn refers.</p>
755          <pre class="programlisting">DBC *name_curs, *job_curs, *join_curs;
756DBC *carray[3];
757DBT key, data;
758int ret, tret;
759
760name_curs = NULL;
761job_curs = NULL;
762memset(&amp;key, 0, sizeof(key));
763memset(&amp;data, 0, sizeof(data));
764
765if ((ret =
766    name_db-&gt;cursor(name_db, txn, &amp;name_curs, 0)) != 0)
767	goto err;
768key.data = "smith";
769key.size = sizeof("smith");
770if ((ret =
771    name_curs-&gt;c_get(name_curs, &amp;key, &amp;data, DB_SET)) != 0)
772	goto err;
773
774if ((ret = job_db-&gt;cursor(job_db, txn, &amp;job_curs, 0)) != 0)
775	goto err;
776key.data = "manager";
777key.size = sizeof("manager");
778if ((ret =
779    job_curs-&gt;c_get(job_curs, &amp;key, &amp;data, DB_SET)) != 0)
780	goto err;
781
782carray[0] = name_curs;
783carray[1] = job_curs;
784carray[2] = NULL;
785
786if ((ret =
787    pers_db-&gt;join(pers_db, carray, &amp;join_curs, 0)) != 0)
788	goto err;
789while ((ret =
790    join_curs-&gt;c_get(join_curs, &amp;key, &amp;data, 0)) == 0) {
791	/* Process record returned in key/data. */
792}
793
794/*
795 * If we exited the loop because we ran out of records,
796 * then it has completed successfully.
797 */
798if (ret == DB_NOTFOUND)
799	ret = 0;
800
801err:
802if (join_curs != NULL &amp;&amp;
803    (tret = join_curs-&gt;c_close(join_curs)) != 0 &amp;&amp; ret == 0)
804	ret = tret;
805if (name_curs != NULL &amp;&amp;
806    (tret = name_curs-&gt;c_close(name_curs)) != 0 &amp;&amp; ret == 0)
807	ret = tret;
808if (job_curs != NULL &amp;&amp;
809    (tret = job_curs-&gt;c_close(job_curs)) != 0 &amp;&amp; ret == 0)
810	ret = tret;
811
812return (ret);
813</pre>
814          <p>The name cursor is positioned at the beginning of the duplicate list
815for <span class="bold"><strong>smith</strong></span> and the job cursor is placed at the beginning of
816the duplicate list for <span class="bold"><strong>manager</strong></span>.  The join cursor is returned
817from the join method.  This code then loops over the join cursor getting
818the personnel records of each one until there are no more.</p>
819        </div>
820      </div>
821      <div class="sect2" lang="en" xml:lang="en">
822        <div class="titlepage">
823          <div>
824            <div>
825              <h3 class="title"><a id="am_count"></a>Data item count</h3>
826            </div>
827          </div>
828        </div>
829        <p>Once a cursor has been initialized to refer to a particular key in the
830database, it can be used to determine the number of data items that are
831stored for any particular key.  The <a href="../api_reference/C/dbccount.html" class="olink">DBC-&gt;count()</a> method returns
832this number of data items.  The returned value is always one, unless
833the database supports duplicate data items, in which case it may be any
834number of items.</p>
835      </div>
836      <div class="sect2" lang="en" xml:lang="en">
837        <div class="titlepage">
838          <div>
839            <div>
840              <h3 class="title"><a id="am_curclose"></a>Cursor close</h3>
841            </div>
842          </div>
843        </div>
844        <p>The <a href="../api_reference/C/dbcclose.html" class="olink">DBC-&gt;close()</a> method closes the <a href="../api_reference/C/dbc.html" class="olink">DBC</a> cursor, after which the
845cursor may no longer be used.  Although cursors are implicitly closed
846when the database they point to are closed, it is good programming
847practice to explicitly close cursors.  In addition, in transactional
848systems, cursors may not exist outside of a transaction and so must be
849explicitly closed.</p>
850      </div>
851    </div>
852    <div class="navfooter">
853      <hr />
854      <table width="100%" summary="Navigation footer">
855        <tr>
856          <td width="40%" align="left"><a accesskey="p" href="am_foreign.html">Prev</a>��</td>
857          <td width="20%" align="center">
858            <a accesskey="u" href="am.html">Up</a>
859          </td>
860          <td width="40%" align="right">��<a accesskey="n" href="am_misc.html">Next</a></td>
861        </tr>
862        <tr>
863          <td width="40%" align="left" valign="top">Foreign key indexes��</td>
864          <td width="20%" align="center">
865            <a accesskey="h" href="index.html">Home</a>
866          </td>
867          <td width="40%" align="right" valign="top">��Chapter��4.��
868		Access Method Wrapup
869        </td>
870        </tr>
871      </table>
872    </div>
873  </body>
874</html>
875