1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
|
<?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.73.2" />
<link rel="start" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="Cursors.html" title="Chapter 4. Using Cursors" />
<link rel="prev" href="ReplacingEntryWCursor.html" title="Replacing Records Using Cursors" />
<link rel="next" href="indexes.html" title="Chapter 5. Secondary Databases" />
</head>
<body>
<div xmlns="" class="navheader">
<div class="libver">
<p>Library Version 11.2.5.3</p>
</div>
<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>
<p>
In
<a class="xref" href="DbUsage.html" title="Database Usage Example">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 <code class="classname">example_database_read</code>
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 <code class="classname">example_database_load</code>
application. See
<a class="xref" href="DbUsage.html#exampledbload" title="Example 3.2 example_database_load">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_c/getting_started</pre>
<p>
where <code class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></code> is the location where you
placed your DB distribution.
</p>
<div class="example">
<a id="CoreEIR"></a>
<p class="title">
<b>Example 4.1 example_database_read</b>
</p>
<div class="example-contents">
<p>
To begin, we include the necessary header files and perform our
forward declarations.
</p>
<a id="c_cursor10"></a>
<pre class="programlisting">/* File: example_database_read.c */
/* gettingstarted_common.h includes db.h for us */
#include "gettingstarted_common.h"
/* Forward declarations */
char * show_inventory_item(void *);
int show_all_records(STOCK_DBS *);
int show_records(STOCK_DBS *, char *);
int show_vendor_record(char *, DB *); </pre>
<p>
Next we write our <code class="function">main()</code> 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="c_cursor11"></a>
<pre class="programlisting">/*
* Displays all inventory items and the associated vendor record.
*/
int
main(int argc, char *argv[])
{
STOCK_DBS my_stock;
int ret;
/* Initialize the STOCK_DBS struct */
initialize_stockdbs(&my_stock);
/*
* Parse the command line arguments here and determine
* the location of the database files. This step is
* omitted for brevity.
*/
/*
* Identify the files that will hold our databases
* This function uses information obtained from the
* command line to identify the directory in which
* the database files reside.
*/
set_db_filenames(&my_stock);
/* Open all databases */
ret = databases_setup(&my_stock, "example_database_read", stderr);
if (ret != 0) {
fprintf(stderr, "Error opening databases\n");
databases_close(&my_stock);
return (ret);
}
ret = show_all_records(&my_stock);
/* close our databases */
databases_close(&my_stock);
return (ret);
} </pre>
<p>
Next we need to write the <code class="function">show_all_records()</code>
function. This
function takes a <code class="literal">STOCK_DBS</code> structure and 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="c_cursor12"></a>
<pre class="programlisting">int show_all_records(STOCK_DBS *my_stock)
{
DBC *cursorp;
DBT key, data;
char *the_vendor;
int exit_value, ret;
/* Initialize our DBTs. */
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
/* Get a cursor to the itemname db */
my_stock->inventory_dbp->cursor(my_stock->inventory_dbp, NULL,
&cursorp, 0);
/*
* Iterate over the inventory database, from the first record
* to the last, displaying each in turn.
*/
exit_value = 0;
while ((ret =
cursorp->get(cursorp, &key, &data, DB_NEXT))
== 0)
{
the_vendor = show_inventory_item(data.data);
ret = show_vendor_record(the_vendor, my_stock->vendor_dbp);
if (ret) {
exit_value = ret;
break;
}
}
/* Close the cursor */
cursorp->close(cursorp);
return(exit_value);
} </pre>
<p>
The <code class="function">show_inventory_item()</code> simply extracts the
inventory information from the record data and displays it. It then
returns the vendor's name. Note that in order to extract the inventory
information, we have to unpack it from the data buffer. How we do this
is entirely dependent on how we packed the buffer in the first
place. For more information, see the
<code class="function">load_inventory_database()</code> function implementation
in
<span><a class="xref" href="DbUsage.html#exampledbload" title="Example 3.2 example_database_load">example_database_load</a>.</span>
</p>
<a id="c_cursor13"></a>
<pre class="programlisting">/*
* Shows an inventory item.
*/
char *
show_inventory_item(void *vBuf)
{
float price;
int buf_pos, quantity;
char *category, *name, *sku, *vendor_name;
char *buf = (char *)vBuf;
/* Get the price. */
price = *((float *)buf);
buf_pos = sizeof(float);
/* Get the quantity. */
quantity = *((int *)(buf + buf_pos));
buf_pos += sizeof(int);
/* Get the inventory item's name */
name = buf + buf_pos;
buf_pos += strlen(name) + 1;
/* Get the inventory item's sku */
sku = buf + buf_pos;
buf_pos += strlen(sku) + 1;
/*
* Get the category (fruits, vegetables, desserts) that this
* item belongs to.
*/
category = buf + buf_pos;
buf_pos += strlen(category) + 1;
/* Get the vendor's name */
vendor_name = buf + buf_pos;
/* Display all this information */
printf("name: %s\n", name);
printf("\tSKU: %s\n", sku);
printf("\tCategory: %s\n", category);
printf("\tPrice: %.2f\n", price);
printf("\tQuantity: %i\n", quantity);
printf("\tVendor:\n");
/* Return the vendor's name */
return(vendor_name);
} </pre>
<p>
Having returned the vendor's name, we can now use it to look up and
display the appropriate vendor 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
<code class="function">get()</code> directly against the vendor database.
</p>
<a id="c_cursor14"></a>
<pre class="programlisting">/*
* Shows a vendor record. Each vendor record is an instance of
* a vendor structure. See load_vendor_database() in
* example_database_load for how this structure was originally
* put into the database.
*/
int
show_vendor_record(char *vendor_name, DB *vendor_dbp)
{
DBT key, data;
VENDOR my_vendor;
int ret;
/* Zero our DBTs */
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
/* Set the search key to the vendor's name */
key.data = vendor_name;
key.size = strlen(vendor_name) + 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.data = &my_vendor;
data.ulen = sizeof(VENDOR);
data.flags = DB_DBT_USERMEM;
/* Get the record */
ret = vendor_dbp->get(vendor_dbp, 0, &key, &data, 0);
if (ret != 0) {
vendor_dbp->err(vendor_dbp, ret,
"Error searching for vendor: '%s'", vendor_name);
return(ret);
} else {
printf("\t\t%s\n", my_vendor.name);
printf("\t\t%s\n", my_vendor.street);
printf("\t\t%s, %s\n", my_vendor.city, my_vendor.state);
printf("\t\t%s\n\n", my_vendor.zipcode);
printf("\t\t%s\n\n", my_vendor.phone_number);
printf("\t\tContact: %s\n", my_vendor.sales_rep);
printf("\t\t%s\n", my_vendor.sales_rep_phone);
}
return(0);
} </pre>
</div>
</div>
<br class="example-break" />
<p>
That completes the implementation of
<code class="classname">example_database_read()</code>. 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>
|