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 <db.h> 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(&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(&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(&my_stock, "example_database_load", stderr); 178 if (ret != 0) { 179 fprintf(stderr, "Error opening databases\n"); 180 databases_close(&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(&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(&my_stock); 194 return (ret); 195 } 196 197 /* close our environment and databases */ 198 databases_close(&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(&my_vendor, 0, sizeof(VENDOR)); 249 /* Zero out the DBTs */ 250 memset(&key, 0, sizeof(DBT)); 251 memset(&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 = &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->put(my_stock.vendor_dbp, 0, &key, &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, &price, &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, &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, &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(&key, 0, sizeof(DBT)); 431 memset(&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->put(my_stock.inventory_dbp, 0, &key, &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