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>Database Usage Example</title>
7    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
8    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
9    <link rel="start" href="index.html" title="Getting Started with Berkeley DB" />
10    <link rel="up" href="DBEntry.html" title="Chapter 3. Database Records" />
11    <link rel="prev" href="cstructs.html" title="Using C Structures with DB" />
12    <link rel="next" href="Cursors.html" title="Chapter 4. Using Cursors" />
13  </head>
14  <body>
15    <div class="navheader">
16      <table width="100%" summary="Navigation header">
17        <tr>
18          <th colspan="3" align="center">Database Usage Example</th>
19        </tr>
20        <tr>
21          <td width="20%" align="left"><a accesskey="p" href="cstructs.html">Prev</a> </td>
22          <th width="60%" align="center">Chapter 3. Database Records</th>
23          <td width="20%" align="right"> <a accesskey="n" href="Cursors.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="DbUsage"></a>Database Usage Example</h2>
33          </div>
34        </div>
35      </div>
36      <p>
37        In <a class="xref" href="CoreDbUsage.html" title="Database Example">Database Example</a> we created several
38        functions that will open and close the databases that we will use for
39        our inventory application. We now make use of those functions to load inventory data into
40        the two databases that we use for this application.
41    </p>
42      <p>
43        Again, remember that you can find the complete implementation for these functions
44        in:
45    </p>
46      <pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
47      <p>
48        where <code class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></code> is the location where you
49        placed your DB distribution.
50    </p>
51      <div class="example">
52        <a id="VENDORStruct"></a>
53        <p class="title">
54          <b>Example 3.1 VENDOR Structure</b>
55        </p>
56        <div class="example-contents">
57          <p>
58            We want to store data related to an inventory system. There are two
59            types of information that we want to manage: inventory data and related
60            vendor contact information. To manage this information, we could
61            create a structure for each type of data, but to illustrate
62            storing mixed data without a structure we refrain from creating one
63            for the inventory data.
64        </p>
65          <p>
66            For the vendor data, we add the VENDOR structure to the same file as holds 
67            our STOCK_DBS structure. Note that the VENDOR structure uses
68            fixed-length fields. This is not necessary and in fact could
69            represent a waste of resources if the number of vendors stored in
70            our database scales to very large numbers. However, for simplicity we use
71            fixed-length fields anyway, especially 
72            given that our sample data contains so few vendor records.
73        </p>
74          <p>
75            Note that for the inventory data, we will store the data by
76            marshaling it into a buffer, described below.
77        </p>
78          <a id="c_dbt10"></a>
79          <pre class="programlisting">/* File: gettingstarted_common.h */
80#include &lt;db.h&gt;
81
82...
83                                                                                                                                     
84<strong class="userinput"><code>typedef struct vendor {
85    char name[MAXFIELD];             /* Vendor name */
86    char street[MAXFIELD];           /* Street name and number */
87    char city[MAXFIELD];             /* City */
88    char state[3];                   /* Two-digit US state code */
89    char zipcode[6];                 /* US zipcode */
90    char phone_number[13];           /* Vendor phone number */
91    char sales_rep[MAXFIELD];        /* Name of sales representative */
92    char sales_rep_phone[MAXFIELD];  /* Sales rep's phone number */
93} VENDOR;</code></strong> </pre>
94        </div>
95      </div>
96      <br class="example-break" />
97      <div class="example">
98        <a id="exampledbload"></a>
99        <p class="title">
100          <b>Example 3.2 example_database_load</b>
101        </p>
102        <div class="example-contents">
103          <p>
104            Our initial sample application will load database information from
105            several flat files. To save space, we won't show all the details of
106            this example program. However, as always you can find the complete
107            implementation for this program here:
108        </p>
109          <pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
110          <p>
111        where <code class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></code> is the location where you
112        placed your DB distribution.
113    </p>
114          <p>
115        We begin with the normal include directives and forward declarations:
116    </p>
117          <a id="c_dbt11"></a>
118          <pre class="programlisting">/* example_database_load.c */
119#include "gettingstarted_common.h"
120                                                                                                                                
121                                                                                                                                
122/* Forward declarations */
123int load_vendors_database(STOCK_DBS, char *);
124int pack_string(char *, char *, int);
125int load_inventory_database(STOCK_DBS, char *); </pre>
126          <p>
127       Next we begin our <code class="function">main()</code> function with the variable
128       declarations and command line parsing that is normal for most command
129       line applications:  
130    </p>
131          <a id="c_dbt12"></a>
132          <pre class="programlisting">/*
133 * Loads the contents of vendors.txt and inventory.txt into
134 * Berkeley DB databases. 
135 */
136int
137main(int argc, char *argv[])
138{
139    STOCK_DBS my_stock;
140    int ret, size;
141    char *basename, *inventory_file, *vendor_file;
142
143    /* Initialize the STOCK_DBS struct */
144    initialize_stockdbs(&amp;my_stock);
145
146   /* 
147    * Initialize the base path. This path is used to 
148    * identify the location of the flat-text data
149    * input files.
150    */
151    basename = "./";
152
153    /* 
154     * Parse the command line arguments here and determine 
155     * the location of the flat text files containing the 
156     * inventory data here. This step is omitted for clarity.
157     */
158                                                                                                                               
159    /* 
160     * Identify the files that will hold our databases 
161     * This function uses information obtained from the
162     * command line to identify the directory in which
163     * the database files reside.
164     */
165    set_db_filenames(&amp;my_stock);
166                                                                                                                                
167    /* Find our input files */
168    size = strlen(basename) + strlen(INVENTORY_FILE) + 1;
169    inventory_file = malloc(size);
170    snprintf(inventory_file, size, "%s%s", basename, INVENTORY_FILE);
171                                                                                                                                
172    size = strlen(basename) + strlen(VENDORS_FILE) + 1;
173    vendor_file = malloc(size);
174    snprintf(vendor_file, size, "%s%s", basename, VENDORS_FILE);
175                                                                                                                                
176    /* Open all databases */
177    ret = databases_setup(&amp;my_stock, "example_database_load", stderr);
178    if (ret != 0) {
179            fprintf(stderr, "Error opening databases\n");
180            databases_close(&amp;my_stock);
181            return (ret);
182    }
183                                                                                                                                
184    ret = load_vendors_database(my_stock, vendor_file);
185    if (!ret) {
186        fprintf(stderr, "Error loading vendors database.\n");
187        databases_close(&amp;my_stock);
188        return (ret);
189    }
190    ret = load_inventory_database(my_stock, inventory_file);
191    if (!ret) {
192        fprintf(stderr, "Error loading inventory database.\n");
193        databases_close(&amp;my_stock);
194        return (ret);
195    }
196
197    /* close our environment and databases */
198    databases_close(&amp;my_stock);
199                                                                                                                                
200    printf("Done loading databases.\n");
201    return (0);
202}</pre>
203          <p>
204        Notice that there is not a lot to this function because we have pushed
205        off all the database activity to other places. In particular our
206        databases are all opened and configured in 
207        <code class="function">databases_setup()</code> which we implemented in 
208        <a class="xref" href="CoreDbUsage.html#databasesetup" title="Example 2.4 The databases_setup() Function">The databases_setup() Function</a>.
209    </p>
210          <p>
211        Next we show the implementation of
212        <code class="function">load_vendors_database()</code>. We load this data by
213        scanning (line by line) the contents of the
214        <code class="filename">vendors.txt</code> into a VENDOR structure. Once we have a
215        line scanned into the structure, we can store that structure into our
216        vendors database. 
217     </p>
218          <p>
219        Note that we use the vendor's name as the key here. In doing so, we
220        assume that the vendor's name is unique in our database. If it was not,
221        we would either have to select a different key, or architect our
222        application such that it could cope with multiple vendor records with
223        the same name.
224     </p>
225          <a id="c_dbt13"></a>
226          <pre class="programlisting">/*
227 * Loads the contents of the vendors.txt file into
228 * a database.
229 */
230int
231load_vendors_database(STOCK_DBS my_stock, char *vendor_file)
232{
233    DBT key, data;
234    FILE *ifp;
235    VENDOR my_vendor;
236    char buf[MAXLINE];
237                                                                                                                               
238    /* Open the vendor file for read access */
239    ifp = fopen(vendor_file, "r");
240    if (ifp == NULL) {
241        fprintf(stderr, "Error opening file '%s'\n", vendor_file);
242        return(-1);
243    }
244                                                                                                                               
245    /* Iterate over the vendor file */
246    while(fgets(buf, MAXLINE, ifp) != NULL) {
247        /* zero out the structure */
248        memset(&amp;my_vendor, 0, sizeof(VENDOR));
249        /* Zero out the DBTs */
250        memset(&amp;key, 0, sizeof(DBT));
251        memset(&amp;data, 0, sizeof(DBT));
252
253        /*
254         * Scan the line into the structure.
255         * Convenient, but not particularly safe.
256         * In a real program, there would be a lot more
257         * defensive code here.
258         */
259        sscanf(buf,
260          "%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]",
261          my_vendor.name, my_vendor.street,
262          my_vendor.city, my_vendor.state,
263          my_vendor.zipcode, my_vendor.phone_number,
264          my_vendor.sales_rep, my_vendor.sales_rep_phone);
265                                                                                                                               
266        /* 
267         * Now that we have our structure we can load it 
268         * into the database. 
269         */
270                                                                                                                               
271        /* Set up the database record's key */
272        key.data = my_vendor.name;
273        key.size = strlen(my_vendor.name) + 1;
274                                                                                                                               
275        /* Set up the database record's data */
276        data.data = &amp;my_vendor;
277        data.size = sizeof(my_vendor);
278                                                                                                                               
279        /*
280         * Note that given the way we built our struct, there are extra
281         * bytes in it. Essentially we're using fixed-width fields with
282         * the unused portion of some fields padded with zeros. This
283         * is the easiest thing to do, but it does result in a bloated
284         * database. Look at load_inventory_data() for an example of how
285         * to avoid this.
286         */
287                                                                                                                               
288        /* Put the data into the database.
289         * Omitting error handling for clarity.
290         */
291        my_stock.vendor_dbp-&gt;put(my_stock.vendor_dbp, 0, &amp;key, &amp;data, 0);
292    } /* end vendors database while loop */
293                                                                                                                               
294    /* Close the vendor.txt file */
295    fclose(ifp);
296    return(0);
297} </pre>
298          <p>
299        Finally, we need to write the
300        <code class="function">load_inventory_database()</code> function. We made this function a
301        bit more complicated than is necessary by avoiding the use of a
302        structure to manage the data. Instead, we manually pack all our inventory
303        data into a single block of memory, and store that data in the
304        database.
305     </p>
306          <p>
307        While this complicates our code somewhat, this approach allows us to
308        use the smallest amount of space possible for the data that we want to
309        store. The result is that our cache can be smaller than it might
310        otherwise be and our database will take less space on disk than if we used
311        a structure with fixed-length fields.
312    </p>
313          <p>
314        For a trivial dataset such as what we use for these examples, these
315        resource savings are negligible. But if we were storing hundreds of
316        millions of records, then the cost savings may become significant.
317    </p>
318          <p>
319        Before we actually implement our inventory loading function, it is useful
320        to create a simple utility function that copies a character array into a
321        buffer at a designated offset:
322    </p>
323          <a id="c_dbt14"></a>
324          <pre class="programlisting">/*
325 * Simple little convenience function that takes a buffer, a string,
326 * and an offset and copies that string into the buffer at the
327 * appropriate location. Used to ensure that all our strings
328 * are contained in a single contiguous chunk of memory.
329 */
330int
331pack_string(char *buffer, char *string, int start_pos)
332{
333    int string_size = strlen(string) + 1;
334
335    memcpy(buffer+start_pos, string, string_size);
336                                                                                                                               
337    return(start_pos + string_size);
338} </pre>
339          <p>
340        That done, we can now load the inventory database:    
341    </p>
342          <a id="c_dbt15"></a>
343          <pre class="programlisting">/*
344 * Loads the contents of the inventory.txt file into
345 * a database.
346 */
347int
348load_inventory_database(STOCK_DBS my_stock, char *inventory_file)
349{
350    DBT key, data;
351    char buf[MAXLINE];
352    void *databuf;
353    int bufLen, dataLen;
354    FILE *ifp;
355                                                                                                                               
356    /*
357     * Rather than lining everything up nicely in a struct, we're being
358     * deliberately a bit sloppy here. This function illustrates how to
359     * store mixed data that might be obtained from various locations
360     * in your application.
361     */
362    float price;
363    int quantity;
364    char category[MAXFIELD], name[MAXFIELD];
365    char vendor[MAXFIELD], sku[MAXFIELD];
366
367    /* Load the inventory database */
368    ifp = fopen(inventory_file, "r");
369    if (ifp == NULL) {
370        fprintf(stderr, "Error opening file '%s'\n", inventory_file);
371        return(-1);
372    }
373                                                                                                                               
374    /* Get our buffer. MAXDATABUF is some suitably large number */
375    databuf = malloc(MAXDATABUF);
376
377    /* 
378     * Read the inventory.txt file line by line, saving each line off to the
379     * database as we go.
380     */
381    while(fgets(buf, MAXLINE, ifp) != NULL) {
382        /*
383         * Scan the line into the appropriate buffers and variables.
384         * Convenient, but not particularly safe. In a real
385         * program, there would be a lot more defensive code here.
386         */
387        sscanf(buf,
388          "%20[^#]#%20[^#]#%f#%i#%20[^#]#%20[^\n]",
389          name, sku, &amp;price, &amp;quantity, category, vendor);
390                                                                                                                               
391        /*
392         * Now pack it into a single contiguous memory location for
393         * storage.
394         */
395        memset(databuf, 0, MAXDATABUF);
396        bufLen = 0;
397        dataLen = 0;
398                                                                                                                               
399        /* 
400         * We first store the fixed-length elements. This makes our code to
401         * retrieve this data from the database a little bit easier.
402         */
403
404        /* First discover how long the data element is. */
405        dataLen = sizeof(float);
406        /* Then copy it to our buffer */
407        memcpy(databuf, &amp;price, dataLen);
408        /* 
409         * Then figure out how much data is actually in our buffer.
410         * We repeat this pattern for all the data we want to store.
411         */
412        bufLen += dataLen;
413                                                                                                                               
414        /* Rinse, lather, repeat. */
415        dataLen = sizeof(int);
416        memcpy(databuf + bufLen, &amp;quantity, dataLen);
417        bufLen += dataLen;
418                                                                                                                               
419        bufLen = pack_string(databuf, name, bufLen);
420        bufLen = pack_string(databuf, sku, bufLen);
421        bufLen = pack_string(databuf, category, bufLen);
422        bufLen = pack_string(databuf, vendor, bufLen);
423
424        /* 
425         * Now actually save the contents of the buffer off 
426         * to our database. 
427         */
428
429        /* Zero out the DBTs */
430        memset(&amp;key, 0, sizeof(DBT));
431        memset(&amp;data, 0, sizeof(DBT));
432                                                                                                                               
433        /* 
434         * The key is the item's SKU. This is a unique value, so we need not
435         * support duplicates for this database. 
436         */
437        key.data = sku;
438        key.size = strlen(sku) + 1;
439                                                                                                                               
440        /* The data is the information that we packed into databuf. */
441        data.data = databuf;
442        data.size = bufLen;
443                                                                                                                               
444        /* Put the data into the database */
445        my_stock.vendor_dbp-&gt;put(my_stock.inventory_dbp, 0, &amp;key, &amp;data, 0);
446    } /* end vendors database while loop */
447                                                                                                                               
448    /* Cleanup */
449    fclose(ifp);
450    if (databuf != NULL)
451        free(databuf);
452                                                                                                                               
453    return(0);
454} </pre>
455          <p>
456        In the next chapter we provide an example that shows how to read
457        the inventory and vendor databases.
458    </p>
459        </div>
460      </div>
461      <br class="example-break" />
462    </div>
463    <div class="navfooter">
464      <hr />
465      <table width="100%" summary="Navigation footer">
466        <tr>
467          <td width="40%" align="left"><a accesskey="p" href="cstructs.html">Prev</a> </td>
468          <td width="20%" align="center">
469            <a accesskey="u" href="DBEntry.html">Up</a>
470          </td>
471          <td width="40%" align="right"> <a accesskey="n" href="Cursors.html">Next</a></td>
472        </tr>
473        <tr>
474          <td width="40%" align="left" valign="top">Using C Structures with DB </td>
475          <td width="20%" align="center">
476            <a accesskey="h" href="index.html">Home</a>
477          </td>
478          <td width="40%" align="right" valign="top"> Chapter 4. Using Cursors</td>
479        </tr>
480      </table>
481    </div>
482  </body>
483</html>
484