290 lines
11 KiB
HTML
290 lines
11 KiB
HTML
<?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>Cursor Example</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="ReplacingEntryWCursor.html" title="Replacing Records Using Cursors" />
|
||
<link rel="next" href="indexes.html" title="Chapter 5. Secondary Databases" />
|
||
</head>
|
||
<body>
|
||
<div class="navheader">
|
||
<table width="100%" summary="Navigation header">
|
||
<tr>
|
||
<th colspan="3" align="center">Cursor Example</th>
|
||
</tr>
|
||
<tr>
|
||
<td width="20%" align="left"><a accesskey="p" href="ReplacingEntryWCursor.html">Prev</a> </td>
|
||
<th width="60%" align="center">Chapter 4. Using Cursors</th>
|
||
<td width="20%" align="right"> <a accesskey="n" href="indexes.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="CoreCursorUsage"></a>Cursor Example</h2>
|
||
</div>
|
||
</div>
|
||
<div></div>
|
||
</div>
|
||
<p>
|
||
In
|
||
|
||
<a href="DbCXXUsage.html">Database Usage Example</a>
|
||
we wrote an
|
||
application that loaded two databases with
|
||
vendor and inventory information. In this example, we will write an
|
||
application to display all of the items in the inventory database. As a
|
||
part of showing any given inventory item, we will look up the vendor who
|
||
can provide the item and show the vendor's contact information.
|
||
</p>
|
||
<p>
|
||
Specifically, the <tt class="classname">example_database_read</tt>
|
||
application does the following:
|
||
</p>
|
||
<div class="orderedlist">
|
||
<ol type="1">
|
||
<li>
|
||
<p>
|
||
Opens the the inventory and vendor databases
|
||
that were created by our <tt class="classname">example_database_load</tt>
|
||
application. See
|
||
|
||
<a href="DbCXXUsage.html#exampledbload-cxx">example_database_load</a>
|
||
for information on how that
|
||
application creates the databases and writes data to them.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>Obtains a cursor from the inventory database.</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
Steps through the inventory database, displaying
|
||
each record as it goes.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
Gets the name of the vendor for that inventory item from the
|
||
inventory record.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
Uses the vendor name to look up the vendor record in the vendor
|
||
database.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>Displays the vendor record.</p>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<p>
|
||
Remember that you can find the complete implementation of this application
|
||
in:
|
||
</p>
|
||
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_cxx/getting_started</pre>
|
||
<p>
|
||
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
|
||
placed your DB distribution.
|
||
</p>
|
||
<div class="example">
|
||
<a id="CoreEIR-cxx"></a>
|
||
<p class="title">
|
||
<b>Example 4.1 example_database_read</b>
|
||
</p>
|
||
<p>
|
||
To begin, we include the necessary header files and perform our
|
||
forward declarations. We also write our <tt class="function">usage()</tt>
|
||
function.
|
||
</p>
|
||
<a id="cxx_cursor10"></a>
|
||
<pre class="programlisting">// File: example_database_read.cpp
|
||
#include <iostream>
|
||
#include <fstream>
|
||
#include <cstdlib>
|
||
|
||
#include "MyDb.hpp"
|
||
#include "gettingStartedCommon.hpp"
|
||
|
||
// Forward declarations
|
||
int show_all_records(MyDb &inventoryDB, MyDb &vendorDB);
|
||
int show_vendor(MyDb &vendorDB, const char *vendor); </pre>
|
||
<p>
|
||
Next we write our <tt class="function">main()</tt> function. Note that it is
|
||
somewhat unnecessarily complicated here because we will be extending it
|
||
in the next chapter to perform inventory item lookups.
|
||
</p>
|
||
<a id="cxx_cursor11"></a>
|
||
<pre class="programlisting">// Displays all inventory items and the associated vendor record.
|
||
int
|
||
main (int argc, char *argv[])
|
||
{
|
||
// Initialize the path to the database files
|
||
std::string databaseHome("./");
|
||
|
||
// Database names
|
||
std::string vDbName("vendordb.db");
|
||
std::string iDbName("inventorydb.db");
|
||
|
||
// Parse the command line arguments
|
||
// Omitted for brevity
|
||
|
||
try
|
||
{
|
||
// Open all databases.
|
||
MyDb inventoryDB(databaseHome, iDbName);
|
||
MyDb vendorDB(databaseHome, vDbName);
|
||
|
||
show_all_records(inventoryDB, vendorDB);
|
||
} catch(DbException &e) {
|
||
std::cerr << "Error reading databases. " << std::endl;
|
||
std::cerr << e.what() << std::endl;
|
||
return(e.get_errno());
|
||
} catch(std::exception &e) {
|
||
std::cerr << "Error reading databases. " << std::endl;
|
||
std::cerr << e.what() << std::endl;
|
||
return(-1);
|
||
}
|
||
|
||
return(0);
|
||
} // End main </pre>
|
||
<p>
|
||
Next we need to write the <tt class="function">show_all_records()</tt>
|
||
function. This function displays all
|
||
of the inventory records found in the inventory database. Once it shows
|
||
the inventory record, it retrieves the vendor's name from that record
|
||
and uses it to look up and display the appropriate vendor record:
|
||
</p>
|
||
<a id="cxx_cursor12"></a>
|
||
<pre class="programlisting">// Shows all the records in the inventory database.
|
||
// For each inventory record shown, the appropriate
|
||
// vendor record is also displayed.
|
||
int
|
||
show_all_records(MyDb &inventoryDB, MyDb &vendorDB)
|
||
{
|
||
// Get a cursor to the inventory db
|
||
Dbc *cursorp;
|
||
try {
|
||
inventoryDB.getDb().cursor(NULL, &cursorp, 0);
|
||
|
||
// Iterate over the inventory database, from the first record
|
||
// to the last, displaying each in turn
|
||
Dbt key, data;
|
||
int ret;
|
||
while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 )
|
||
{
|
||
InventoryData inventoryItem(data.get_data());
|
||
inventoryItem.show();
|
||
|
||
show_vendor(vendorDB, inventoryItem.getVendor().c_str());
|
||
}
|
||
} catch(DbException &e) {
|
||
inventoryDB.getDb().err(e.get_errno(), "Error in show_all_records");
|
||
cursorp->close();
|
||
throw e;
|
||
} catch(std::exception &e) {
|
||
cursorp->close();
|
||
throw e;
|
||
}
|
||
|
||
cursorp->close();
|
||
return (0);
|
||
} </pre>
|
||
<p>
|
||
Note that the <tt class="classname">InventoryData</tt> class that we use here
|
||
is described in
|
||
<a href="DbCXXUsage.html#InventoryData">InventoryData Class</a>.
|
||
</p>
|
||
<p>
|
||
Having displayed the inventory record, we now want to display the
|
||
vendor record corresponding to this record.
|
||
In this case we do not need to use a
|
||
cursor to display the vendor record. Using a cursor here complicates our
|
||
code slightly for no good gain. Instead, we simply perform a
|
||
<tt class="function">get()</tt> directly against the vendor database.
|
||
</p>
|
||
<a id="cxx_cursor13"></a>
|
||
<pre class="programlisting">// Shows a vendor record. Each vendor record is an instance of
|
||
// a vendor structure. See loadVendorDB() in
|
||
// example_database_load for how this structure was originally
|
||
// put into the database.
|
||
int
|
||
show_vendor(MyDb &vendorDB, const char *vendor)
|
||
{
|
||
Dbt data;
|
||
VENDOR my_vendor;
|
||
|
||
try {
|
||
// Set the search key to the vendor's name
|
||
// vendor is explicitly cast to char * to stop a compiler
|
||
// complaint.
|
||
Dbt key((char *)vendor, strlen(vendor) + 1);
|
||
|
||
// Make sure we use the memory we set aside for the VENDOR
|
||
// structure rather than the memory that DB allocates.
|
||
// Some systems may require structures to be aligned in memory
|
||
// in a specific way, and DB may not get it right.
|
||
|
||
data.set_data(&my_vendor);
|
||
data.set_ulen(sizeof(VENDOR));
|
||
data.set_flags(DB_DBT_USERMEM);
|
||
|
||
// Get the record
|
||
vendorDB.getDb().get(NULL, &key, &data, 0);
|
||
std::cout << " " << my_vendor.street << "\n"
|
||
<< " " << my_vendor.city << ", "
|
||
<< my_vendor.state << "\n"
|
||
<< " " << my_vendor.zipcode << "\n"
|
||
<< " " << my_vendor.phone_number << "\n"
|
||
<< " Contact: " << my_vendor.sales_rep << "\n"
|
||
<< " " << my_vendor.sales_rep_phone
|
||
<< std::endl;
|
||
|
||
} catch(DbException &e) {
|
||
vendorDB.getDb().err(e.get_errno(), "Error in show_vendor");
|
||
throw e;
|
||
} catch(std::exception &e) {
|
||
throw e;
|
||
}
|
||
return (0);
|
||
} </pre>
|
||
</div>
|
||
<p>
|
||
That completes the implementation of
|
||
<tt class="classname">example_database_read()</tt>. In the next chapter, we
|
||
will extend this application to make use of a secondary database so that
|
||
we can query the inventory database for a specific inventory item.
|
||
</p>
|
||
</div>
|
||
<div class="navfooter">
|
||
<hr />
|
||
<table width="100%" summary="Navigation footer">
|
||
<tr>
|
||
<td width="40%" align="left"><a accesskey="p" href="ReplacingEntryWCursor.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="indexes.html">Next</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="40%" align="left" valign="top">Replacing Records Using Cursors </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="h" href="index.html">Home</a>
|
||
</td>
|
||
<td width="40%" align="right" valign="top"> Chapter 5. Secondary Databases</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</body>
|
||
</html>
|