hamsterdb Embedded Database  2.1.1
env3.cpp
Go to the documentation of this file.
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 }