Import BSDDB 4.7.25 (as of svn r89086)
This commit is contained in:
581
docs/gsg/CXX/Positioning.html
Normal file
581
docs/gsg/CXX/Positioning.html
Normal file
@@ -0,0 +1,581 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Getting Records Using the Cursor</title>
|
||||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
|
||||
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
|
||||
<link rel="up" href="Cursors.html" title="Chapter 4. Using Cursors" />
|
||||
<link rel="previous" href="Cursors.html" title="Chapter 4. Using Cursors" />
|
||||
<link rel="next" href="PutEntryWCursor.html" title="Putting Records Using Cursors" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Getting Records Using the Cursor</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Chapter 4. Using Cursors</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="Positioning"></a>Getting Records Using the Cursor</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
To iterate over database records, from the first record to
|
||||
the last, simply open the cursor and then use the
|
||||
|
||||
|
||||
<tt class="methodname">Dbc::get()</tt>
|
||||
method.
|
||||
<span>Note that you need to supply the
|
||||
<tt class="literal">DB_NEXT</tt> flag to this method.</span>
|
||||
For example:
|
||||
</p>
|
||||
<a id="cxx_cursor3"></a>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
|
||||
...
|
||||
|
||||
Db my_database(NULL, 0);
|
||||
Dbc *cursorp;
|
||||
|
||||
try {
|
||||
// Database open omitted for clarity
|
||||
|
||||
// Get a cursor
|
||||
my_database.cursor(NULL, &cursorp, 0);
|
||||
|
||||
Dbt key, data;
|
||||
int ret;
|
||||
|
||||
// Iterate over the database, retrieving each record in turn.
|
||||
while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) {
|
||||
// Do interesting things with the Dbts here.
|
||||
}
|
||||
if (ret != DB_NOTFOUND) {
|
||||
// ret should be DB_NOTFOUND upon exiting the loop.
|
||||
// Dbc::get() will by default throw an exception if any
|
||||
// significant errors occur, so by default this if block
|
||||
// can never be reached.
|
||||
}
|
||||
} catch(DbException &e) {
|
||||
my_database.err(e.get_errno(), "Error!");
|
||||
} catch(std::exception &e) {
|
||||
my_database.errx("Error! %s", e.what());
|
||||
}
|
||||
|
||||
// Cursors must be closed
|
||||
if (cursorp != NULL)
|
||||
cursorp->close();
|
||||
|
||||
my_database.close(0);</pre>
|
||||
<p>
|
||||
To iterate over the database from the last record to the first, use
|
||||
<tt class="literal">DB_PREV</tt> instead of <tt class="literal">DB_NEXT</tt>:
|
||||
</p>
|
||||
<a id="cxx_cursor4"></a>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
|
||||
...
|
||||
|
||||
Db my_database(NULL, 0);
|
||||
Dbc *cursorp;
|
||||
|
||||
try {
|
||||
// Database open omitted for clarity
|
||||
|
||||
// Get a cursor
|
||||
my_database.cursor(NULL, &cursorp, 0);
|
||||
|
||||
Dbt key, data;
|
||||
int ret;
|
||||
// Iterate over the database, retrieving each record in turn.
|
||||
while ((ret = cursorp->get(&key, &data, DB_PREV)) == 0) {
|
||||
// Do interesting things with the Dbts here.
|
||||
}
|
||||
if (ret != DB_NOTFOUND) {
|
||||
// ret should be DB_NOTFOUND upon exiting the loop.
|
||||
// Dbc::get() will by default throw an exception if any
|
||||
// significant errors occur, so by default this if block
|
||||
// can never be reached.
|
||||
}
|
||||
} catch(DbException &e) {
|
||||
my_database.err(e.get_errno(), "Error!");
|
||||
} catch(std::exception &e) {
|
||||
my_database.errx("Error! %s", e.what());
|
||||
}
|
||||
|
||||
// Cursors must be closed
|
||||
if (cursorp != NULL)
|
||||
cursorp->close();
|
||||
|
||||
my_database.close(0);</pre>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="cursorsearch"></a>Searching for Records</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
You can use cursors to search for database records. You can search based
|
||||
on just a key, or you can search based on both the key and the data.
|
||||
You can also perform partial matches if your database supports sorted
|
||||
duplicate sets. In all cases, the key and data parameters of these
|
||||
methods are filled with the key and data values of the database record
|
||||
to which the cursor is positioned as a result of the search.
|
||||
</p>
|
||||
<p>
|
||||
Also, if the search fails, then cursor's state is left unchanged
|
||||
and
|
||||
|
||||
<tt class="literal">DB_NOTFOUND</tt>
|
||||
is returned.
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
To use a cursor to search for a record, use
|
||||
|
||||
<span>Dbt::get()<tt class="methodname"></tt>.</span>
|
||||
When you use this method, you can provide the following flags:
|
||||
</p>
|
||||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||||
<h3 class="title">Note</h3>
|
||||
<p>
|
||||
Notice in the following list that the cursor flags use the
|
||||
keyword <tt class="literal">SET</tt> when the cursor examines just the key
|
||||
portion of the records (in this case, the cursor is set to the
|
||||
record whose key matches the value provided to the cursor).
|
||||
Moreover, when the cursor uses the keyword <tt class="literal">GET</tt>,
|
||||
then the cursor is positioned to both the key
|
||||
<span class="emphasis"><em>and</em></span> the data values provided to the cursor.
|
||||
</p>
|
||||
<p>
|
||||
Regardless of the keyword you use to get a record with a cursor, the
|
||||
cursor's key and data
|
||||
|
||||
<span><tt class="classname">Dbt</tt>s</span>
|
||||
are filled with the data retrieved from the record to which the
|
||||
cursor is positioned.
|
||||
</p>
|
||||
</div>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="literal">DB_SET</tt>
|
||||
</p>
|
||||
<p>
|
||||
Moves the cursor to the first record in the database with
|
||||
the specified key.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="literal">DB_SET_RANGE</tt>
|
||||
</p>
|
||||
<p>
|
||||
<span>Identical to
|
||||
<tt class="literal">DB_SET</tt>
|
||||
|
||||
unless you are using the BTree access. In this case, the cursor
|
||||
moves</span>
|
||||
|
||||
|
||||
to the first record in the database whose
|
||||
key is greater than or equal to the specified key. This comparison
|
||||
is determined by the
|
||||
|
||||
<span>comparison function</span>
|
||||
that you provide for the database. If no
|
||||
|
||||
<span>comparison function</span>
|
||||
is provided, then the default
|
||||
|
||||
lexicographical sorting is used.
|
||||
</p>
|
||||
<p>
|
||||
For example, suppose you have database records that use the
|
||||
following
|
||||
<span>Strings</span>
|
||||
|
||||
as keys:
|
||||
</p>
|
||||
<pre class="programlisting">Alabama
|
||||
Alaska
|
||||
Arizona</pre>
|
||||
<p>
|
||||
Then providing a search key of <tt class="literal">Alaska</tt> moves the
|
||||
cursor to the second key noted above. Providing a key of
|
||||
<tt class="literal">Al</tt> moves the cursor to the first key (<tt class="literal">Alabama</tt>), providing
|
||||
a search key of <tt class="literal">Alas</tt> moves the cursor to the second key
|
||||
(<tt class="literal">Alaska</tt>), and providing a key of <tt class="literal">Ar</tt> moves the
|
||||
cursor to the last key (<tt class="literal">Arizona</tt>).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="literal">DB_GET_BOTH</tt>
|
||||
</p>
|
||||
<p>
|
||||
Moves the cursor to the first record in the database that uses
|
||||
the specified key and data.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="literal">DB_GET_BOTH_RANGE</tt>
|
||||
</p>
|
||||
<p>
|
||||
Moves the cursor to the first record in the database whose key matches the specified
|
||||
key and whose data is
|
||||
greater than or equal to the specified data. If the database supports
|
||||
duplicate records, then on matching the key, the cursor is moved to
|
||||
the duplicate record with the smallest data that is greater than or
|
||||
equal to the specified data.
|
||||
</p>
|
||||
<p>
|
||||
For example,
|
||||
|
||||
<span>suppose your database uses BTree
|
||||
and it has </span>
|
||||
database records that use the following key/data pairs:
|
||||
</p>
|
||||
<pre class="programlisting">Alabama/Athens
|
||||
Alabama/Florence
|
||||
Alaska/Anchorage
|
||||
Alaska/Fairbanks
|
||||
Arizona/Avondale
|
||||
Arizona/Florence </pre>
|
||||
<p>then providing:</p>
|
||||
<div class="informaltable">
|
||||
<table border="1" width="80%">
|
||||
<colgroup>
|
||||
<col />
|
||||
<col />
|
||||
<col />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a search key of ...</th>
|
||||
<th>and a search data of ...</th>
|
||||
<th>moves the cursor to ...</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Alaska</td>
|
||||
<td>Fa</td>
|
||||
<td>Alaska/Fairbanks</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Arizona</td>
|
||||
<td>Fl</td>
|
||||
<td>Arizona/Florence</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alaska</td>
|
||||
<td>An</td>
|
||||
<td>Alaska/Anchorage</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
For example, assuming a database containing sorted duplicate records of
|
||||
U.S. States/U.S Cities key/data pairs (both as
|
||||
<span>Strings),</span>
|
||||
|
||||
then the following code fragment can be used to position the cursor
|
||||
to any record in the database and print its key/data values:
|
||||
|
||||
</p>
|
||||
<a id="cxx_cursor5"></a>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
#include <string.h>
|
||||
|
||||
...
|
||||
|
||||
Db my_database(NULL, 0);
|
||||
Dbc *cursorp;
|
||||
|
||||
try {
|
||||
// database open omitted for clarity
|
||||
|
||||
// Get a cursor
|
||||
my_database.cursor(NULL, &cursorp, 0);
|
||||
|
||||
// Search criteria
|
||||
char *search_key = "Alaska";
|
||||
char *search_data = "Fa";
|
||||
|
||||
// Set up our DBTs
|
||||
Dbt key(search_key, strlen(search_key) + 1);
|
||||
Dbt data(search_data, strlen(search_data) + 1);
|
||||
|
||||
// Position the cursor to the first record in the database whose
|
||||
// key matches the search key and whose data begins with the search
|
||||
// data.
|
||||
int ret = cursorp->get(&key, &data, DB_GET_BOTH_RANGE);
|
||||
if (!ret) {
|
||||
// Do something with the data
|
||||
}
|
||||
} catch(DbException &e) {
|
||||
my_database.err(e.get_errno(), "Error!");
|
||||
} catch(std::exception &e) {
|
||||
my_database.errx("Error! %s", e.what());
|
||||
}
|
||||
|
||||
// Close the cursor
|
||||
if (cursorp != NULL)
|
||||
cursorp->close();
|
||||
|
||||
// Close the database
|
||||
my_database.close(0); </pre>
|
||||
</div>
|
||||
<div class="sect2" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="title"><a id="getdups"></a>Working with Duplicate Records</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
A record is a duplicate of another record if the two records share the
|
||||
same key. For duplicate records, only the data portion of the record is unique.
|
||||
</p>
|
||||
<p>
|
||||
Duplicate records are supported only for the BTree or Hash access methods.
|
||||
For information on configuring your database to use duplicate records,
|
||||
see <a href="btree.html#duplicateRecords">Allowing Duplicate Records</a>.
|
||||
</p>
|
||||
<p>
|
||||
If your database supports duplicate records, then it can potentially
|
||||
contain multiple records that share the same key.
|
||||
|
||||
|
||||
|
||||
<span>By default, normal database
|
||||
get operations will only return the first such record in a set
|
||||
of duplicate records. Typically, subsequent duplicate records are
|
||||
accessed using a cursor.
|
||||
</span>
|
||||
|
||||
The following
|
||||
|
||||
|
||||
<span><tt class="methodname">Dbc::get()</tt> flags</span>
|
||||
are interesting when working with databases that support duplicate records:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<span>
|
||||
<tt class="literal">DB_NEXT</tt>,
|
||||
<tt class="literal">DB_PREV</tt>
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Shows the next/previous record in the database, regardless of
|
||||
whether it is a duplicate of the current record. For an example of
|
||||
using these methods, see <a href="Positioning.html">Getting Records Using the Cursor</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="literal">DB_GET_BOTH_RANGE</tt>
|
||||
</p>
|
||||
<p>
|
||||
Useful for seeking the cursor to a specific record, regardless of
|
||||
whether it is a duplicate record. See <a href="Positioning.html#cursorsearch">Searching for Records</a> for more
|
||||
information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<span>
|
||||
<tt class="literal">DB_NEXT_NODUP</tt>,
|
||||
<tt class="literal">DB_PREV_NODUP</tt>
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Gets the next/previous non-duplicate record in the database. This
|
||||
allows you to skip over all the duplicates in a set of duplicate
|
||||
records. If you call
|
||||
|
||||
<span>
|
||||
|
||||
<tt class="methodname">Dbc::get()</tt>
|
||||
with <tt class="literal">DB_PREV_NODUP</tt>,
|
||||
</span>
|
||||
then the cursor is positioned to the last record for the previous
|
||||
key in the database. For example, if you have the following records
|
||||
in your database:
|
||||
</p>
|
||||
<pre class="programlisting">Alabama/Athens
|
||||
Alabama/Florence
|
||||
Alaska/Anchorage
|
||||
Alaska/Fairbanks
|
||||
Arizona/Avondale
|
||||
Arizona/Florence</pre>
|
||||
<p>
|
||||
and your cursor is positioned to <tt class="literal">Alaska/Fairbanks</tt>,
|
||||
and you then call
|
||||
|
||||
<span>
|
||||
|
||||
<tt class="methodname">Dbc::get()</tt>
|
||||
with <tt class="literal">DB_PREV_NODUP</tt>,
|
||||
</span>
|
||||
then the cursor is positioned to Alabama/Florence. Similarly, if
|
||||
you call
|
||||
|
||||
<span>
|
||||
|
||||
<tt class="methodname">Dbc::get()</tt>
|
||||
with <tt class="literal">DB_NEXT_NODUP</tt>,
|
||||
</span>
|
||||
|
||||
then the cursor is positioned to the first record corresponding to
|
||||
the next key in the database.
|
||||
</p>
|
||||
<p>
|
||||
If there is no next/previous key in the database, then
|
||||
|
||||
<tt class="literal">DB_NOTFOUND</tt>
|
||||
is returned, and the cursor is left unchanged.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
<tt class="literal">DB_NEXT_DUP</tt>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
Gets the
|
||||
|
||||
<span>next</span>
|
||||
record that shares the current key. If the
|
||||
cursor is positioned at the last record in the duplicate set and
|
||||
you call
|
||||
|
||||
<span>
|
||||
|
||||
<tt class="methodname">Dbc::get()</tt>
|
||||
with <tt class="literal">DB_NEXT_DUP</tt>,
|
||||
</span>
|
||||
|
||||
then
|
||||
|
||||
<tt class="literal">DB_NOTFOUND</tt>
|
||||
is returned and the cursor is left unchanged.
|
||||
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
For example, the following code fragment positions a cursor to a key
|
||||
|
||||
|
||||
|
||||
<span>and displays it and all its
|
||||
duplicates.</span>
|
||||
|
||||
|
||||
</p>
|
||||
<a id="cxx_cursor6"></a>
|
||||
<pre class="programlisting">#include <db_cxx.h>
|
||||
#include <string.h>
|
||||
|
||||
...
|
||||
|
||||
char *search_key = "Al";
|
||||
|
||||
Db my_database(NULL, 0);
|
||||
Dbc *cursorp;
|
||||
|
||||
try {
|
||||
// database open omitted for clarity
|
||||
|
||||
// Get a cursor
|
||||
my_database.cursor(NULL, &cursorp, 0);
|
||||
|
||||
// Set up our DBTs
|
||||
Dbt key(search_key, strlen(search_key) + 1);
|
||||
Dbt data;
|
||||
|
||||
// Position the cursor to the first record in the database whose
|
||||
// key and data begin with the correct strings.
|
||||
int ret = cursorp->get(&key, &data, DB_SET);
|
||||
while (ret != DB_NOTFOUND) {
|
||||
std::cout << "key: " << (char *)key.get_data()
|
||||
<< "data: " << (char *)data.get_data()<< std::endl;
|
||||
ret = cursorp->get(&key, &data, DB_NEXT_DUP);
|
||||
}
|
||||
} catch(DbException &e) {
|
||||
my_database.err(e.get_errno(), "Error!");
|
||||
} catch(std::exception &e) {
|
||||
my_database.errx("Error! %s", e.what());
|
||||
}
|
||||
|
||||
// Close the cursor
|
||||
if (cursorp != NULL)
|
||||
cursorp->close();
|
||||
|
||||
// Close the database
|
||||
my_database.close(0); </pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="Cursors.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">Chapter 4. Using Cursors </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top"> Putting Records Using Cursors</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user