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