|
hamsterdb Embedded Database
2.1.1
|
00001 00015 #include <iostream> 00016 #include <stdlib.h> /* for exit() */ 00017 #include <ham/hamsterdb.hpp> 00018 00019 #define MAX_DBS 3 00020 00021 #define DBNAME_CUSTOMER 1 00022 #define DBNAME_ORDER 2 00023 #define DBNAME_C2O 3 /* C2O: Customer To Order */ 00024 00025 #define DBIDX_CUSTOMER 0 00026 #define DBIDX_ORDER 1 00027 #define DBIDX_C2O 2 00028 00029 #define MAX_CUSTOMERS 4 00030 #define MAX_ORDERS 8 00031 00032 /* A structure for the "customer" database */ 00033 typedef struct { 00034 int id; /* customer id - will be the key of the 00035 customer table */ 00036 char name[32]; /* customer name */ 00037 /* ... additional information could follow here */ 00038 } customer_t; 00039 00040 /* A structure for the "orders" database */ 00041 typedef struct { 00042 int id; /* order id - will be the key of the 00043 order table */ 00044 int customer_id; /* customer id */ 00045 char assignee[32]; /* assigned to whom? */ 00046 /* ... additional information could follow here */ 00047 } order_t; 00048 00049 int 00050 run_demo() { 00051 int i; 00052 hamsterdb::env env; /* hamsterdb environment */ 00053 hamsterdb::db db[MAX_DBS]; /* hamsterdb database objects */ 00054 hamsterdb::cursor cursor[MAX_DBS]; /* a cursor for each database */ 00055 hamsterdb::key key, cust_key, ord_key, c2o_key; 00056 hamsterdb::record record, cust_record, ord_record, c2o_record; 00057 00058 customer_t customers[MAX_CUSTOMERS] = { 00059 { 1, "Alan Antonov Corp." }, 00060 { 2, "Barry Broke Inc." }, 00061 { 3, "Carl Caesar Lat." }, 00062 { 4, "Doris Dove Brd." } 00063 }; 00064 00065 order_t orders[MAX_ORDERS] = { 00066 { 1, 1, "Joe" }, 00067 { 2, 1, "Tom" }, 00068 { 3, 3, "Joe" }, 00069 { 4, 4, "Tom" }, 00070 { 5, 3, "Ben" }, 00071 { 6, 3, "Ben" }, 00072 { 7, 4, "Chris" }, 00073 { 8, 1, "Ben" } 00074 }; 00075 00076 /* Create a new hamsterdb environment */ 00077 env.create("test.db"); 00078 00079 /* 00080 * Then create the two Databases in this Environment; each Database 00081 * has a name - the first is our "customer" Database, the second 00082 * is for the "orders"; the third manages our 1:n relation and 00083 * therefore needs to enable duplicate keys 00084 */ 00085 db[DBIDX_CUSTOMER] = env.create_db(DBNAME_CUSTOMER); 00086 db[DBIDX_ORDER] = env.create_db(DBNAME_ORDER); 00087 db[DBIDX_C2O] = env.create_db(DBNAME_C2O, HAM_ENABLE_DUPLICATES); 00088 00089 /* Create a cursor for each database */ 00090 for (i = 0; i < MAX_DBS; i++) 00091 cursor[i].create(&db[i]); 00092 00093 /* 00094 * Insert the customers in the customer table 00095 * 00096 * INSERT INTO customers VALUES (1, "Alan Antonov Corp."); 00097 * INSERT INTO customers VALUES (2, "Barry Broke Inc."); 00098 * etc 00099 */ 00100 for (i = 0; i < MAX_CUSTOMERS; i++) { 00101 key.set_size(sizeof(int)); 00102 key.set_data(&customers[i].id); 00103 00104 record.set_size(sizeof(customer_t)); 00105 record.set_data(&customers[i]); 00106 00107 db[0].insert(&key, &record); 00108 } 00109 00110 /* 00111 * And now the orders in the second database; contrary to env1, 00112 * we only store the assignee, not the whole structure 00113 * 00114 * INSERT INTO orders VALUES (1, "Joe"); 00115 * INSERT INTO orders VALUES (2, "Tom"); 00116 */ 00117 for (i = 0; i < MAX_ORDERS; i++) { 00118 key.set_size(sizeof(int)); 00119 key.set_data(&orders[i].id); 00120 00121 record.set_size(sizeof(orders[i].assignee)); 00122 record.set_data(orders[i].assignee); 00123 00124 db[1].insert(&key, &record); 00125 } 00126 00127 /* 00128 * And now the 1:n relationships; the flag HAM_DUPLICATE creates 00129 * a duplicate key, if the key already exists 00130 * 00131 * INSERT INTO c2o VALUES (1, 1); 00132 * INSERT INTO c2o VALUES (2, 1); 00133 * etc 00134 */ 00135 for (i = 0; i < MAX_ORDERS; i++) { 00136 key.set_size(sizeof(int)); 00137 key.set_data(&orders[i].customer_id); 00138 00139 record.set_size(sizeof(int)); 00140 record.set_data(&orders[i].id); 00141 00142 db[2].insert(&key, &record, HAM_DUPLICATE); 00143 } 00144 00145 /* 00146 * Now start the query - we want to dump each customer with his 00147 * orders 00148 * 00149 * loop over the customer; for each customer, loop over the 1:n table 00150 * and pick those orders with the customer id. then load the order 00151 * and print it 00152 * 00153 * the outer loop is similar to 00154 * SELECT * FROM customers WHERE 1; 00155 */ 00156 while (1) { 00157 customer_t *customer; 00158 00159 try { 00160 cursor[0].move_next(&cust_key, &cust_record); 00161 } 00162 catch (hamsterdb::error &e) { 00163 /* reached end of the database? */ 00164 if (e.get_errno() == HAM_KEY_NOT_FOUND) 00165 break; 00166 else { 00167 std::cerr << "cursor.move_next() failed: " << e.get_string() 00168 << std::endl; 00169 return (-1); 00170 } 00171 } 00172 00173 customer = (customer_t *)cust_record.get_data(); 00174 00175 /* print the customer id and name */ 00176 std::cout << "customer " << customer->id << " ('" 00177 << customer->name << "')" << std::endl; 00178 00179 /* 00180 * Loop over the 1:n table 00181 * 00182 * before we start the loop, we move the cursor to the 00183 * first duplicate key 00184 * 00185 * SELECT * FROM customers, orders, c2o 00186 * WHERE c2o.customer_id=customers.id AND 00187 * c2o.order_id=orders.id; 00188 */ 00189 c2o_key.set_data(&customer->id); 00190 c2o_key.set_size(sizeof(int)); 00191 00192 try { 00193 cursor[2].find(&c2o_key); 00194 } 00195 catch (hamsterdb::error &e) { 00196 if (e.get_errno() == HAM_KEY_NOT_FOUND) 00197 continue; 00198 else { 00199 std::cerr << "cursor.find() failed: " << e.get_string() 00200 << std::endl; 00201 return (-1); 00202 } 00203 } 00204 00205 /* get the record of this database entry */ 00206 cursor[2].move(0, &c2o_record); 00207 00208 do { 00209 int order_id; 00210 00211 order_id = *(int *)c2o_record.get_data(); 00212 ord_key.set_data(&order_id); 00213 ord_key.set_size(sizeof(int)); 00214 00215 /* 00216 * Load the order 00217 * SELECT * FROM orders WHERE id = order_id; 00218 */ 00219 ord_record = db[1].find(&ord_key); 00220 00221 std::cout << " order: " << order_id << " (assigned to " 00222 << (char *)ord_record.get_data() << ")" << std::endl; 00223 00224 /* 00225 * the flag HAM_ONLY_DUPLICATES restricts the cursor 00226 * movement to the duplicate list. 00227 */ 00228 try { 00229 cursor[2].move(&c2o_key, &c2o_record, 00230 HAM_CURSOR_NEXT | HAM_ONLY_DUPLICATES); 00231 } 00232 catch (hamsterdb::error &e) { 00233 /* reached end of the database? */ 00234 if (e.get_errno() == HAM_KEY_NOT_FOUND) 00235 break; 00236 else { 00237 std::cerr << "cursor.move() failed: " << e.get_string() 00238 << std::endl; 00239 return (-1); 00240 } 00241 } 00242 00243 } while (1); 00244 } 00245 00246 /* 00247 * we're done! no need to cleanup, the destructors will prevent memory 00248 * leaks 00249 */ 00250 std::cout << "success!" << std::endl; 00251 return (0); 00252 } 00253 00254 int 00255 main(int argc, char **argv) 00256 { 00257 try { 00258 return (run_demo()); 00259 } 00260 catch (hamsterdb::error &e) { 00261 std::cerr << "run_demo() failed with unexpected error " 00262 << e.get_errno() << " ('" 00263 << e.get_string() << "')" << std::endl; 00264 return (-1); 00265 } 00266 }
1.7.6.1