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