hamsterdb Embedded Database 1.1.15
|
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