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