hamsterdb Embedded Database 1.1.14

env2.c

Go to the documentation of this file.
00001 
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <stdlib.h> /* for exit() */
00020 #if UNDER_CE
00021 #   include <windows.h>
00022 #endif
00023 #include <ham/hamsterdb.h>
00024 
00025 void 
00026 error(const char *foo, ham_status_t st)
00027 {
00028 #if UNDER_CE
00029     wchar_t title[1024];
00030     wchar_t text[1024];
00031 
00032     MultiByteToWideChar(CP_ACP, 0, foo, -1, title, 
00033             sizeof(title)/sizeof(wchar_t));
00034     MultiByteToWideChar(CP_ACP, 0, ham_strerror(st), -1, text, 
00035             sizeof(text)/sizeof(wchar_t));
00036 
00037     MessageBox(0, title, text, 0);
00038 #endif
00039     printf("%s() returned error %d: %s\n", foo, st, ham_strerror(st));
00040     exit(-1);
00041 }
00042 
00043 #define MAX_DBS             3
00044 
00045 #define DBNAME_CUSTOMER     1
00046 #define DBNAME_ORDER        2
00047 #define DBNAME_C2O          3   /* C2O: Customer To Order */
00048 
00049 #define DBIDX_CUSTOMER      0
00050 #define DBIDX_ORDER         1
00051 #define DBIDX_C2O           2
00052 
00053 #define MAX_CUSTOMERS       4
00054 #define MAX_ORDERS          8
00055 
00056 /* 
00057  * a structure for the "customer" database
00058  */
00059 typedef struct
00060 {
00061     int id;                 /* customer id - will be the key of the 
00062                                customer table */
00063     char name[32];          /* customer name */
00064     /* ... additional information could follow here */
00065 } customer_t;
00066 
00067 /* 
00068  * a structure for the "orders" database
00069  */
00070 typedef struct
00071 {
00072     int id;                 /* order id - will be the key of the 
00073                                order table */
00074     int customer_id;        /* customer id */
00075     char assignee[32];      /* assigned to whom? */
00076     /* ... additional information could follow here */
00077 } order_t;
00078 
00079 int 
00080 main(int argc, char **argv)
00081 {
00082     int i;
00083     ham_status_t st;        /* status variable */
00084     ham_db_t *db[MAX_DBS];  /* hamsterdb database objects */
00085     ham_env_t *env;         /* hamsterdb environment */
00086     ham_cursor_t *cursor[MAX_DBS]; /* a cursor for each database */
00087     ham_key_t key, cust_key, ord_key, c2o_key;
00088     ham_record_t record, cust_record, ord_record, c2o_record;
00089 
00090     customer_t customers[MAX_CUSTOMERS]={
00091         { 1, "Alan Antonov Corp." },
00092         { 2, "Barry Broke Inc." },
00093         { 3, "Carl Caesar Lat." },
00094         { 4, "Doris Dove Brd." }
00095     };
00096 
00097     order_t orders[MAX_ORDERS]={
00098         { 1, 1, "Joe" },
00099         { 2, 1, "Tom" },
00100         { 3, 3, "Joe" },
00101         { 4, 4, "Tom" },
00102         { 5, 3, "Ben" },
00103         { 6, 3, "Ben" },
00104         { 7, 4, "Chris" },
00105         { 8, 1, "Ben" }
00106     };
00107 
00108     memset(&key, 0, sizeof(key));
00109     memset(&record, 0, sizeof(record));
00110     memset(&cust_key, 0, sizeof(cust_key));
00111     memset(&cust_record, 0, sizeof(cust_record));
00112     memset(&ord_key, 0, sizeof(ord_key));
00113     memset(&ord_record, 0, sizeof(ord_record));
00114     memset(&c2o_key, 0, sizeof(c2o_key));
00115     memset(&c2o_record, 0, sizeof(c2o_record));
00116 
00117     /*
00118      * first, create a new hamsterdb environment 
00119      */
00120     st=ham_env_new(&env);
00121     if (st!=HAM_SUCCESS)
00122         error("ham_env_new", st);
00123 
00124     /*
00125      * then create the database objects
00126      */
00127     for (i=0; i<MAX_DBS; i++) {
00128         st=ham_new(&db[i]);
00129         if (st!=HAM_SUCCESS)
00130             error("ham_new", st);
00131     }
00132 
00133     /*
00134      * Now create a new database file for the Environment
00135      */
00136     st=ham_env_create_ex(env, "test.db", 0, 0664, 0);
00137     if (st!=HAM_SUCCESS)
00138         error("ham_env_create", st);
00139 
00140     /*
00141      * Then create the two Databases in this Environment; each Database
00142      * has a name - the first is our "customer" Database, the second 
00143      * is for the "orders"; the third manages our 1:n relation and
00144      * therefore needs to enable duplicate keys
00145      */
00146     st=ham_env_create_db(env, db[DBIDX_CUSTOMER], DBNAME_CUSTOMER, 0, 0);
00147     if (st!=HAM_SUCCESS)
00148         error("ham_env_create_db(customer)", st);
00149     st=ham_env_create_db(env, db[DBIDX_ORDER], DBNAME_ORDER, 0, 0);
00150     if (st!=HAM_SUCCESS)
00151         error("ham_env_create_db(order)", st);
00152     st=ham_env_create_db(env, db[DBIDX_C2O], DBNAME_C2O, 
00153             HAM_ENABLE_DUPLICATES, 0);
00154     if (st!=HAM_SUCCESS)
00155         error("ham_env_create_db(c2o)", st);
00156 
00157     /* 
00158      * create a Cursor for each Database
00159      */
00160     for (i=0; i<MAX_DBS; i++) {
00161         st=ham_cursor_create(db[i], 0, 0, &cursor[i]);
00162         if (st!=HAM_SUCCESS) 
00163             error("ham_cursor_create" , st);
00164     }
00165 
00166     /*
00167      * Insert the customers in the customer table
00168      *
00169      * INSERT INTO customers VALUES (1, "Alan Antonov Corp.");
00170      * INSERT INTO customers VALUES (2, "Barry Broke Inc.");
00171      * etc
00172      */
00173     for (i=0; i<MAX_CUSTOMERS; i++) {
00174         key.size=sizeof(int);
00175         key.data=&customers[i].id;
00176 
00177         record.size=sizeof(customer_t);
00178         record.data=&customers[i];
00179 
00180         st=ham_insert(db[0], 0, &key, &record, 0);
00181         if (st!=HAM_SUCCESS)
00182             error("ham_insert (customer)", st);
00183     }
00184 
00185     /*
00186      * And now the orders in the second Database; contrary to env1, 
00187      * we only store the assignee, not the whole structure
00188      *
00189      * INSERT INTO orders VALUES (1, "Joe");
00190      * INSERT INTO orders VALUES (2, "Tom");
00191      */
00192     for (i=0; i<MAX_ORDERS; i++) {
00193         key.size=sizeof(int);
00194         key.data=&orders[i].id;
00195 
00196         record.size=sizeof(orders[i].assignee);
00197         record.data=orders[i].assignee;
00198 
00199         st=ham_insert(db[1], 0, &key, &record, 0);
00200         if (st!=HAM_SUCCESS)
00201             error("ham_insert (order)", st);
00202     }
00203 
00204     /*
00205      * and now the 1:n relationships; the flag HAM_DUPLICATE creates
00206      * a duplicate key, if the key already exists
00207      *
00208      * INSERT INTO c2o VALUES (1, 1);
00209      * INSERT INTO c2o VALUES (2, 1);
00210      * etc
00211      */
00212     for (i=0; i<MAX_ORDERS; i++) {
00213         key.size=sizeof(int);
00214         key.data=&orders[i].customer_id;
00215 
00216         record.size=sizeof(int);
00217         record.data=&orders[i].id;
00218 
00219         st=ham_insert(db[2], 0, &key, &record, HAM_DUPLICATE);
00220         if (st!=HAM_SUCCESS)
00221             error("ham_insert(c2o)", st);
00222     }
00223 
00224     /*
00225      * now start the query - we want to dump each customer with his
00226      * orders
00227      *
00228      * loop over the customer; for each customer, loop over the 1:n table
00229      * and pick those orders with the customer id. then load the order
00230      * and print it
00231      *
00232      * the outer loop is similar to 
00233      * SELECT * FROM customers WHERE 1;
00234      */
00235     while (1) {
00236         customer_t *customer;
00237 
00238         st=ham_cursor_move(cursor[0], &cust_key, &cust_record, HAM_CURSOR_NEXT);
00239         if (st!=HAM_SUCCESS) {
00240             /* reached end of the database? */
00241             if (st==HAM_KEY_NOT_FOUND)
00242                 break;
00243             else
00244                 error("ham_cursor_next(customer)", st);
00245         }
00246 
00247         customer=(customer_t *)cust_record.data;
00248 
00249         /* print the customer id and name */
00250         printf("customer %d ('%s')\n", customer->id, customer->name);
00251 
00252         /*
00253          * loop over the 1:n table
00254          *
00255          * before we start the loop, we move the cursor to the
00256          * first duplicate key
00257          *
00258          * SELECT * FROM customers, orders, c2o 
00259          *   WHERE c2o.customer_id=customers.id AND
00260          *      c2o.order_id=orders.id;
00261          */
00262         c2o_key.data=&customer->id;
00263         c2o_key.size=sizeof(int);
00264         st=ham_cursor_find(cursor[2], &c2o_key, 0);
00265         if (st!=HAM_SUCCESS) {
00266             if (st==HAM_KEY_NOT_FOUND)
00267                 continue;
00268             error("ham_cursor_find(c2o)", st);
00269         }
00270         st=ham_cursor_move(cursor[2], 0, &c2o_record, 0);
00271         if (st!=HAM_SUCCESS)
00272             error("ham_cursor_move(c2o)", st);
00273 
00274         do {
00275             int order_id;
00276 
00277             order_id=*(int *)c2o_record.data;
00278             ord_key.data=&order_id;
00279             ord_key.size=sizeof(int);
00280 
00281             /* 
00282              * load the order 
00283              * SELECT * FROM orders WHERE id = order_id;
00284              */
00285             st=ham_find(db[1], 0, &ord_key, &ord_record, 0);
00286             if (st!=HAM_SUCCESS)
00287                 error("ham_find(order)", st);
00288 
00289             printf("  order: %d (assigned to %s)\n", 
00290                     order_id, (char *)ord_record.data);
00291 
00292             /*
00293              * the flag HAM_ONLY_DUPLICATES restricts the cursor
00294              * movement to the duplicate list.
00295              */
00296             st=ham_cursor_move(cursor[2], &c2o_key, 
00297                     &c2o_record, HAM_CURSOR_NEXT|HAM_ONLY_DUPLICATES);
00298             if (st!=HAM_SUCCESS) {
00299                 /* reached end of the database? */
00300                 if (st==HAM_KEY_NOT_FOUND)
00301                     break;
00302                 else
00303                     error("ham_cursor_next(c2o)", st);
00304             }
00305         } while(1);
00306     }
00307 
00308     /*
00309      * Now close the Environment handle; the flag
00310      * HAM_AUTO_CLEANUP will automatically close all Databases and
00311      * Cursors
00312      */
00313     st=ham_env_close(env, HAM_AUTO_CLEANUP);
00314     if (st!=HAM_SUCCESS)
00315         error("ham_env_close", st);
00316 
00317     for (i=0; i<MAX_DBS; i++)
00318          ham_delete(db[i]);
00319 
00320     ham_env_delete(env);
00321 
00322 
00323 #if UNDER_CE
00324     error("success", 0);
00325 #endif
00326     printf("success!\n");
00327     return (0);
00328 }
00329 
00330 #if UNDER_CE
00331 int 
00332 _tmain(int argc, _TCHAR* argv[])
00333 {
00334     return (main(0, 0));
00335 }
00336 #endif