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="usingDbt.html" title="Reading and Writing Database Records" />
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="usingDbt.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="DbCXXUsage"></a>Database Usage Example</h2>
33          </div>
34        </div>
35        <div></div>
36      </div>
37      <p>
38        In <a href="CoreDbCXXUsage.html">Database Example</a> we created 
39        a class that opens and closes a database for us.
40        We now make use of that class to load inventory data into
41        two databases that we will use for our inventory system.
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_cxx/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="VENDORCXXStruct"></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            have created 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            We now show the definition of the VENDOR structure.
67            Note that the VENDOR structure uses fixed-length fields. 
68            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        <a id="cxx_dbt10"></a>
75        <pre class="programlisting">// File: gettingStartedCommon.hpp
76#define MAXFIELD 20
77typedef struct vendor {
78    char name[MAXFIELD];             // Vendor name
79    char street[MAXFIELD];           // Street name and number
80    char city[MAXFIELD];             // City
81    char state[3];                   // Two-digit US state code
82    char zipcode[6];                 // US zipcode
83    char phone_number[13];           // Vendor phone number
84    char sales_rep[MAXFIELD];        // Name of sales representative
85    char sales_rep_phone[MAXFIELD];  // Sales rep's phone number
86} VENDOR;</pre>
87      </div>
88      <div class="example">
89        <a id="InventoryData"></a>
90        <p class="title">
91          <b>Example 3.2 InventoryData Class</b>
92        </p>
93        <p>
94            In order to manage our actual inventory data, we create a class that
95            encapsulates the data that we want to store for each inventory
96            record. Beyond simple data encapsulation, this class is also capable
97            of marshaling the inventory data into a single contiguous buffer
98            for the purposes of storing in that data in a DB database.
99        </p>
100        <p>
101            We also provide two constructors for this class. The default
102            constructor simply initializes all our data members for us. A second
103            constructor is also provided that is capable of populating our data
104            members from a <tt class="literal">void *</tt>. This second constructor is
105            not really needed until the next chapter where we show how to read
106            data from the databases, but we include it here for the purpose of
107            completeness anyway.
108        </p>
109        <p>
110            To simplify things a bit, we include the entire implementation for this
111            class in <tt class="filename">gettingStartedCommon.hpp</tt> along with
112            our <tt class="literal">VENDOR</tt> structure definition.
113        </p>
114        <p>
115            To begin, we create the public getter and setter methods that we
116            use with our class' private members. We also show the implementation
117            of the method that we use to initialize all our private members.
118        </p>
119        <a id="cxx_dbt11"></a>
120        <pre class="programlisting">class InventoryData
121{
122public:
123    inline void setPrice(double price) {price_ = price;}
124    inline void setQuantity(long quantity) {quantity_ = quantity;}
125    inline void setCategory(std::string &amp;category) {category_ = category;}
126    inline void setName(std::string &amp;name) {name_ = name;}
127    inline void setVendor(std::string &amp;vendor) {vendor_ = vendor;}
128    inline void setSKU(std::string &amp;sku) {sku_ = sku;}
129                                                                                                                                    
130    inline double&amp; getPrice() {return(price_);}
131    inline long&amp; getQuantity() {return(quantity_);}
132    inline std::string&amp; getCategory() {return(category_);}
133    inline std::string&amp; getName() {return(name_);}
134    inline std::string&amp; getVendor() {return(vendor_);}
135    inline std::string&amp; getSKU() {return(sku_);}
136                                                                                                                                    
137    // Initialize our data members
138    void clear()
139    {
140        price_ = 0.0;
141        quantity_ = 0;
142        category_.clear();
143        name_.clear();
144        vendor_.clear();
145        sku_.clear();
146    } </pre>
147        <p>
148        Next we implement our constructors. The default constructor simply calls
149        the <tt class="methodname">clear()</tt>. The second constructor takes a
150        <tt class="literal">void *</tt> as an argument, which it then uses to
151        initialize the data members. Note, again, that we will not actually use
152        this second constructor in this chapter, but we show it here just to be
153        complete anyway.
154    </p>
155        <a id="cxx_dbt12"></a>
156        <pre class="programlisting">    // Default constructor
157    InventoryData() { clear(); }
158                                                                                                                                    
159    // Constructor from a void *
160    // For use with the data returned from a bdb get
161    InventoryData(void *buffer)
162    {
163        char *buf = (char *)buffer;
164                                                                                                                                    
165        price_ = *((double *)buf);
166        bufLen_ = sizeof(double);
167                                                                                                                                    
168        quantity_ = *((long *)(buf + bufLen_));
169        bufLen_ += sizeof(long);
170                                                                                                                                    
171        name_ = buf + bufLen_;
172        bufLen_ += name_.size() + 1;
173                                                                                                                                    
174        sku_ = buf + bufLen_;
175        bufLen_ += sku_.size() + 1;
176                                                                                                                                    
177        category_ = buf + bufLen_;
178        bufLen_ += category_.size() + 1;
179                                                                                                                                    
180        vendor_ = buf + bufLen_;
181        bufLen_ += vendor_.size() + 1;
182    } </pre>
183        <p>
184        Next we provide a couple of methods for returning the class' buffer and
185        the size of the buffer. These are used for actually storing the class'
186        data in a DB database.
187    </p>
188        <a id="cxx_dbt13"></a>
189        <pre class="programlisting">    // Marshalls this classes data members into a single
190    // contiguous memory location for the purpose of storing
191    // the data in a database.
192    char *
193    getBuffer()
194    {
195        // Zero out the buffer
196        memset(databuf_, 0, 500);
197        // Now pack the data into a single contiguous memory location for
198        // storage.
199        bufLen_ = 0;
200        int dataLen = 0;
201                                                                                                                                    
202        dataLen = sizeof(double);
203        memcpy(databuf_, &amp;price_, dataLen);
204        bufLen_ += dataLen;
205                                                                                                                                    
206        dataLen = sizeof(long);
207        memcpy(databuf_ + bufLen_, &amp;quantity_, dataLen);
208        bufLen_ += dataLen;
209                                                                                                                                    
210        packString(databuf_, name_);
211        packString(databuf_, sku_);
212        packString(databuf_, category_);
213        packString(databuf_, vendor_);
214                                                                                                                                    
215        return (databuf_);
216    }
217                                                                                                                                    
218    // Returns the size of the buffer. Used for storing
219    // the buffer in a database.
220    inline int getBufferSize() { return (bufLen_); } </pre>
221        <p>
222        Our last public method is a utility method that we use to get the class
223        to show itself.
224    </p>
225        <a id="cxx_dbt14"></a>
226        <pre class="programlisting">     // Utility function used to show the contents of this class
227    void
228    show() {
229        std::cout &lt;&lt; "\nName:         " &lt;&lt; name_ &lt;&lt; std::endl;
230        std::cout &lt;&lt; "    SKU:        " &lt;&lt; sku_ &lt;&lt; std::endl;
231        std::cout &lt;&lt; "    Price:      " &lt;&lt; price_ &lt;&lt; std::endl;
232        std::cout &lt;&lt; "    Quantity:   " &lt;&lt; quantity_ &lt;&lt; std::endl;
233        std::cout &lt;&lt; "    Category:   " &lt;&lt; category_ &lt;&lt; std::endl;
234        std::cout &lt;&lt; "    Vendor:     " &lt;&lt; vendor_ &lt;&lt; std::endl;
235    } </pre>
236        <p>
237        Finally, we provide a private method that is used to help us pack data
238        into our buffer, and we declare our private data members.
239    </p>
240        <a id="cxx_dbt15"></a>
241        <pre class="programlisting">private:
242
243    // Utility function that appends a char * to the end of
244    // the buffer.
245    void
246    packString(char *buffer, std::string &amp;theString)
247    {
248        int string_size = theString.size() + 1;
249        memcpy(buffer+bufLen_, theString.c_str(), string_size);
250        bufLen_ += string_size;
251    }
252
253    // Data members
254    std::string category_, name_, vendor_, sku_;
255    double price_;
256    long quantity_;
257    int bufLen_;
258    char databuf_[500];
259}; </pre>
260      </div>
261      <div class="example">
262        <a id="exampledbload-cxx"></a>
263        <p class="title">
264          <b>Example 3.3 example_database_load</b>
265        </p>
266        <p>
267            Our initial sample application loads database information from
268            several flat files. To save space, we won't show all the details of
269            this example program. However, as always you can find the complete
270            implementation for this program here:
271        </p>
272        <pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_cxx/getting_started</pre>
273        <p>
274        where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
275        placed your DB distribution.
276    </p>
277        <p>
278        We begin with the normal include directives and forward declarations:
279    </p>
280        <a id="cxx_dbt16"></a>
281        <pre class="programlisting">// File: example_database_load.cpp
282#include &lt;iostream&gt;
283#include &lt;fstream&gt;
284#include &lt;cstdlib&gt;
285                                                                                                                                    
286#include "MyDb.hpp"
287#include "gettingStartedCommon.hpp" 
288
289// Forward declarations
290void loadVendorDB(MyDb&amp;, std::string&amp;);
291void loadInventoryDB(MyDb&amp;, std::string&amp;);
292</pre>
293        <p>
294       Next we begin our <tt class="function">main()</tt> function with the variable
295       declarations and command line parsing that is normal for most command
296       line applications:  
297    </p>
298        <a id="cxx_dbt17"></a>
299        <pre class="programlisting">// Loads the contents of vendors.txt and inventory.txt into
300// Berkeley DB databases. 
301int
302main(int argc, char *argv[])
303{
304    // Initialize the path to the database files
305    std::string basename("./");
306    std::string databaseHome("./");
307                                                                                                                                    
308    // Database names
309    std::string vDbName("vendordb.db");
310    std::string iDbName("inventorydb.db");
311
312    // Parse the command line arguments here and determine 
313    // the location of the flat text files containing the 
314    // inventory data here. This step is omitted for clarity.
315
316    //  Identify the full name for our input files, which should
317    //  also include some path information.
318    std::string inventoryFile = basename + "inventory.txt";
319    std::string vendorFile = basename + "vendors.txt";
320                                                                                                                                    
321    try
322    {
323        // Open all databases.
324        MyDb inventoryDB(databaseHome, iDbName);
325        MyDb vendorDB(databaseHome, vDbName);
326                                                                                                                                    
327        // Load the vendor database
328        loadVendorDB(vendorDB, vendorFile);
329
330        // Load the inventory database
331        loadInventoryDB(inventoryDB, inventoryFile);
332    } catch(DbException &amp;e) {
333        std::cerr &lt;&lt; "Error loading databases. " &lt;&lt; std::endl;
334        std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
335        return(e.get_errno());
336    } catch(std::exception &amp;e) {
337        std::cerr &lt;&lt; "Error loading databases. " &lt;&lt; std::endl;
338        std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
339        return(-1);
340    }
341                                                                                                                                    
342    return(0);
343} // End main </pre>
344        <p>
345        Note that we do not explicitly close our databases here. This is because
346        the databases are encapsulated in <tt class="classname">MyDb</tt> class
347        objects, and those objects are on the stack. When they go out of scope,
348        their destructors will cause the database close to occur.
349    </p>
350        <p>
351        Notice that there is not a lot to this function because we have pushed
352        off all the database activity to other places.
353    </p>
354        <p>
355        Next we show the implementation of
356        <tt class="function">loadVendorDB()</tt>. We load this data by
357        scanning (line by line) the contents of the
358        <tt class="filename">vendors.txt</tt> file into a VENDOR structure. Once we have a
359        line scanned into the structure, we can store that structure into our
360        vendors database. 
361     </p>
362        <p>
363        Note that we use the vendor's name as the key here. In doing so, we
364        assume that the vendor's name is unique in our database. If it was not,
365        we would either have to select a different key, or architect our
366        application such that it could cope with multiple vendor records with
367        the same name.
368     </p>
369        <a id="cxx_dbt18"></a>
370        <pre class="programlisting">// Loads the contents of the vendors.txt file into a database
371void
372loadVendorDB(MyDb &amp;vendorDB, std::string &amp;vendorFile)
373{
374    std::ifstream inFile(vendorFile.c_str(), std::ios::in);
375    if ( !inFile )
376    {
377        std::cerr &lt;&lt; "Could not open file '" &lt;&lt; vendorFile
378                  &lt;&lt; "'. Giving up." &lt;&lt; std::endl;
379        throw std::exception();
380    }
381                                                                                                                                    
382    VENDOR my_vendor;
383    while (!inFile.eof())
384    {
385        std::string stringBuf;
386        std::getline(inFile, stringBuf);
387        memset(&amp;my_vendor, 0, sizeof(VENDOR));
388                                                                                                                                    
389        // Scan the line into the structure.
390        // Convenient, but not particularly safe.
391        // In a real program, there would be a lot more
392        // defensive code here.
393        sscanf(stringBuf.c_str(),
394          "%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]",
395          my_vendor.name, my_vendor.street,
396          my_vendor.city, my_vendor.state,
397          my_vendor.zipcode, my_vendor.phone_number,
398          my_vendor.sales_rep, my_vendor.sales_rep_phone);
399                                                                                                                                    
400        Dbt key(my_vendor.name, strlen(my_vendor.name) + 1);
401        Dbt data(&amp;my_vendor, sizeof(VENDOR));
402                                                                                                                                    
403        vendorDB.getDb().put(NULL, &amp;key, &amp;data, 0);
404    }
405    inFile.close();
406} </pre>
407        <p>
408        Finally, we need to write the
409        <tt class="function">loadInventoryDB()</tt> function. To load the inventory information, 
410        we read in each line of the inventory.txt file, obtain each field from
411        it, then we load this data into an <tt class="classname">InventoryData</tt>
412        instance. 
413     </p>
414        <p>
415        To help us obtain the various fields from each line of input,
416        we also create a simple helper function that locates the position of the
417        first a field delimiter (a pound (#) sign) from a line of input.
418     </p>
419        <p>
420        Note that we could have simply decided to store our inventory data in a
421        structure very much like the VENDOR structure that we use above.
422        However, by storing this data in the
423        <tt class="classname">InventoryData</tt> class, which identifies the size of
424        the data that it contains, 
425        we can use the smallest amount of space possible for the data that we
426        are storing.  The result is that our cache can be smaller than it might
427        otherwise be and our database will take less space on disk than if we used
428        a structure with fixed-length fields.
429    </p>
430        <p>
431        For a trivial dataset such as what we use for these examples, these
432        resource savings are negligible. But if we were storing hundreds of
433        millions of records, then the cost savings may become significant.
434    </p>
435        <a id="cxx_dbt19"></a>
436        <pre class="programlisting">// Used to locate the first pound sign (a field delimiter)
437// in the input string.
438int
439getNextPound(std::string &amp;theString, std::string &amp;substring)
440{
441    int pos = theString.find("#");
442    substring.assign(theString, 0, pos);
443    theString.assign(theString, pos + 1, theString.size());
444    return (pos);
445}
446                                                                                                                                    
447                                                                                                                                    
448// Loads the contents of the inventory.txt file into a database
449void
450loadInventoryDB(MyDb &amp;inventoryDB, std::string &amp;inventoryFile)
451{
452    InventoryData inventoryData;
453    std::string substring;
454    int nextPound;
455                                                                                                                                    
456    std::ifstream inFile(inventoryFile.c_str(), std::ios::in);
457    if (!inFile)
458    {
459        std::cerr &lt;&lt; "Could not open file '" &lt;&lt; inventoryFile
460                  &lt;&lt; "'. Giving up." &lt;&lt; std::endl;
461        throw std::exception();
462    }
463                                                                                                                                    
464    while (!inFile.eof())
465    {
466        inventoryData.clear();
467        std::string stringBuf;
468        std::getline(inFile, stringBuf);
469                                                                                                                                    
470        // Now parse the line
471        if (!stringBuf.empty())
472        {
473            nextPound = getNextPound(stringBuf, substring);
474            inventoryData.setName(substring);
475                                                                                                                                    
476            nextPound = getNextPound(stringBuf, substring);
477            inventoryData.setSKU(substring);
478                                                                                                                                    
479            nextPound = getNextPound(stringBuf, substring);
480            inventoryData.setPrice(strtod(substring.c_str(), 0));
481                                                                                                                                    
482            nextPound = getNextPound(stringBuf, substring);
483            inventoryData.setQuantity(strtol(substring.c_str(), 0, 10));
484                                                                                                                                    
485            nextPound = getNextPound(stringBuf, substring);
486            inventoryData.setCategory(substring);
487                                                                                                                                    
488            nextPound = getNextPound(stringBuf, substring);
489            inventoryData.setVendor(substring);
490                                                                                                                                    
491            void *buff = (void *)inventoryData.getSKU().c_str();
492            int size = inventoryData.getSKU().size()+1;
493            Dbt key(buff, size);
494                                                                                                                                    
495            buff = inventoryData.getBuffer();
496            size = inventoryData.getBufferSize();
497            Dbt data(buff, size);
498                                                                                                                                    
499            inventoryDB.getDb().put(NULL, &amp;key, &amp;data, 0);
500        }
501    }
502    inFile.close();
503} </pre>
504        <p>
505        In the next chapter we provide an example that shows how to read
506        the inventory and vendor databases.
507    </p>
508      </div>
509    </div>
510    <div class="navfooter">
511      <hr />
512      <table width="100%" summary="Navigation footer">
513        <tr>
514          <td width="40%" align="left"><a accesskey="p" href="usingDbt.html">Prev</a>��</td>
515          <td width="20%" align="center">
516            <a accesskey="u" href="DBEntry.html">Up</a>
517          </td>
518          <td width="40%" align="right">��<a accesskey="n" href="Cursors.html">Next</a></td>
519        </tr>
520        <tr>
521          <td width="40%" align="left" valign="top">Reading and Writing Database Records��</td>
522          <td width="20%" align="center">
523            <a accesskey="h" href="index.html">Home</a>
524          </td>
525          <td width="40%" align="right" valign="top">��Chapter��4.��Using Cursors</td>
526        </tr>
527      </table>
528    </div>
529  </body>
530</html>
531