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(&amp;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(&amp;my_stock);
150                                                                                                                                
151    /* Open all databases */
152    ret = databases_setup(&amp;my_stock, "example_database_read", stderr);
153    if (ret != 0) {
154        fprintf(stderr, "Error opening databases\n");
155        databases_close(&amp;my_stock);
156        return (ret);
157    }
158                                                                                                                                
159    ret = show_all_records(&amp;my_stock);
160
161    /* close our databases */
162    databases_close(&amp;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(&amp;key, 0, sizeof(DBT));
183    memset(&amp;data, 0, sizeof(DBT));
184                                                                                                                                  
185    /* Get a cursor to the itemname db */
186    my_stock-&gt;inventory_dbp-&gt;cursor(my_stock-&gt;inventory_dbp, NULL,
187      &amp;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-&gt;get(cursorp, &amp;key, &amp;data, DB_NEXT))
196      == 0)
197    {
198        the_vendor = show_inventory_item(data.data);
199        ret = show_vendor_record(the_vendor, my_stock-&gt;vendor_dbp);
200        if (ret) {
201            exit_value = ret;
202            break;
203        }
204    }
205                                                                                                                                  
206    /* Close the cursor */
207    cursorp-&gt;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(&amp;key, 0, sizeof(DBT));
294    memset(&amp;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 = &amp;my_vendor;
308    data.ulen = sizeof(VENDOR);
309    data.flags = DB_DBT_USERMEM;
310                                                                                                                                  
311    /* Get the record */
312    ret = vendor_dbp-&gt;get(vendor_dbp, 0, &amp;key, &amp;data, 0);
313    if (ret != 0) {
314        vendor_dbp-&gt;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