1// File: excxx_example_database_read.cpp 2 3#include <iostream> 4#include <fstream> 5#include <cstdlib> 6 7#include "MyDb.hpp" 8#include "gettingStartedCommon.hpp" 9 10#ifdef _WIN32 11extern "C" { 12 extern int getopt(int, char * const *, const char *); 13 extern char *optarg; 14} 15#else 16#include <unistd.h> 17#endif 18 19// Forward declarations 20int show_item(MyDb &itemnameSDB, MyDb &vendorDB, std::string &itemName); 21int show_all_records(MyDb &inventoryDB, MyDb &vendorDB); 22int show_vendor(MyDb &vendorDB, const char *vendor); 23 24int 25usage() 26{ 27 std::cout << "example_database_read [-i <path to data files>]" 28 << " [-h <database home directory>]" << std::endl; 29 30 std::cout << "Note: Any path specified to the -h parameter must end" 31 << " with your system's path delimiter (/ or \\)" 32 << std::endl; 33 return (-1); 34} 35 36int 37main (int argc, char *argv[]) 38{ 39 40 char ch, lastChar; 41 42 // Initialize the path to the database files 43 std::string databaseHome("./"); 44 std::string itemName; 45 46 // Database names 47 std::string vDbName("vendordb.db"); 48 std::string iDbName("inventorydb.db"); 49 std::string itemSDbName("itemname.sdb"); 50 51 // Parse the command line arguments 52 while ((ch = getopt(argc, argv, "h:i:")) != EOF) 53 switch (ch) { 54 case 'h': 55 databaseHome = optarg; 56 lastChar = databaseHome[databaseHome.size() -1]; 57 if (lastChar != '/' && lastChar != '\\') 58 return (usage()); 59 break; 60 case 'i': 61 itemName = optarg; 62 break; 63 case '?': 64 default: 65 return (usage()); 66 break; 67 } 68 69 try 70 { 71 // Open all databases. 72 MyDb inventoryDB(databaseHome, iDbName); 73 MyDb vendorDB(databaseHome, vDbName); 74 MyDb itemnameSDB(databaseHome, itemSDbName, true); 75 76 // Associate the secondary to the primary 77 inventoryDB.getDb().associate(NULL, 78 &(itemnameSDB.getDb()), 79 get_item_name, 80 0); 81 82 if (itemName.empty()) 83 { 84 show_all_records(inventoryDB, vendorDB); 85 } else { 86 show_item(itemnameSDB, vendorDB, itemName); 87 } 88 } catch(DbException &e) { 89 std::cerr << "Error reading databases. " << std::endl; 90 return (e.get_errno()); 91 } catch(std::exception &e) { 92 std::cerr << "Error reading databases. " << std::endl; 93 std::cerr << e.what() << std::endl; 94 return (-1); 95 } 96 97 return (0); 98} // End main 99 100// Shows the records in the inventory database that 101// have a specific item name. For each inventory record 102// shown, the appropriate vendor record is also displayed. 103int 104show_item(MyDb &itemnameSDB, MyDb &vendorDB, std::string &itemName) 105{ 106 107 // Get a cursor to the itemname secondary db 108 Dbc *cursorp; 109 110 try { 111 itemnameSDB.getDb().cursor(NULL, &cursorp, 0); 112 113 // Get the search key. This is the name on the inventory 114 // record that we want to examine. 115 std::cout << "Looking for " << itemName << std::endl; 116 Dbt key((void *)itemName.c_str(), (u_int32_t)itemName.length() + 1); 117 Dbt data; 118 119 // Position the cursor to the first record in the secondary 120 // database that has the appropriate key. 121 int ret = cursorp->get(&key, &data, DB_SET); 122 if (!ret) { 123 do { 124 InventoryData inventoryItem(data.get_data()); 125 inventoryItem.show(); 126 127 show_vendor(vendorDB, inventoryItem.getVendor().c_str()); 128 129 } while (cursorp->get(&key, &data, DB_NEXT_DUP) == 0); 130 } else { 131 std::cerr << "No records found for '" << itemName 132 << "'" << std::endl; 133 } 134 } catch(DbException &e) { 135 itemnameSDB.getDb().err(e.get_errno(), "Error in show_item"); 136 cursorp->close(); 137 throw e; 138 } catch(std::exception &e) { 139 itemnameSDB.getDb().errx("Error in show_item: %s", e.what()); 140 cursorp->close(); 141 throw e; 142 } 143 144 cursorp->close(); 145 return (0); 146} 147 148// Shows all the records in the inventory database. 149// For each inventory record shown, the appropriate 150// vendor record is also displayed. 151int 152show_all_records(MyDb &inventoryDB, MyDb &vendorDB) 153{ 154 155 // Get a cursor to the inventory db 156 Dbc *cursorp; 157 try { 158 inventoryDB.getDb().cursor(NULL, &cursorp, 0); 159 160 // Iterate over the inventory database, from the first record 161 // to the last, displaying each in turn 162 Dbt key, data; 163 int ret; 164 while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) 165 { 166 InventoryData inventoryItem(data.get_data()); 167 inventoryItem.show(); 168 169 show_vendor(vendorDB, inventoryItem.getVendor().c_str()); 170 } 171 } catch(DbException &e) { 172 inventoryDB.getDb().err(e.get_errno(), "Error in show_all_records"); 173 cursorp->close(); 174 throw e; 175 } catch(std::exception &e) { 176 cursorp->close(); 177 throw e; 178 } 179 180 cursorp->close(); 181 return (0); 182} 183 184// Shows a vendor record. Each vendor record is an instance of 185// a vendor structure. See loadVendorDB() in 186// example_database_load for how this structure was originally 187// put into the database. 188int 189show_vendor(MyDb &vendorDB, const char *vendor) 190{ 191 Dbt data; 192 VENDOR my_vendor; 193 194 try { 195 // Set the search key to the vendor's name 196 // vendor is explicitly cast to char * to stop a compiler 197 // complaint. 198 Dbt key((char *)vendor, (u_int32_t)strlen(vendor) + 1); 199 200 // Make sure we use the memory we set aside for the VENDOR 201 // structure rather than the memory that DB allocates. 202 // Some systems may require structures to be aligned in memory 203 // in a specific way, and DB may not get it right. 204 205 data.set_data(&my_vendor); 206 data.set_ulen(sizeof(VENDOR)); 207 data.set_flags(DB_DBT_USERMEM); 208 209 // Get the record 210 vendorDB.getDb().get(NULL, &key, &data, 0); 211 std::cout << " " << my_vendor.street << "\n" 212 << " " << my_vendor.city << ", " 213 << my_vendor.state << "\n" 214 << " " << my_vendor.zipcode << "\n" 215 << " " << my_vendor.phone_number << "\n" 216 << " Contact: " << my_vendor.sales_rep << "\n" 217 << " " << my_vendor.sales_rep_phone 218 << std::endl; 219 220 } catch(DbException &e) { 221 vendorDB.getDb().err(e.get_errno(), "Error in show_vendor"); 222 throw e; 223 } catch(std::exception &e) { 224 throw e; 225 } 226 return (0); 227} 228