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