upscaledb  2.2.1
env2.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2016 Christoph Rupp (chris@crupp.de).
3  * All Rights Reserved.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * See the file COPYING for License information.
16  */
17 
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h> /* for exit() */
27 #include <ups/upscaledb.h>
28 
29 void
30 error(const char *foo, ups_status_t st) {
31  printf("%s() returned error %d: %s\n", foo, st, ups_strerror(st));
32  exit(-1);
33 }
34 
35 #define MAX_DBS 3
36 
37 #define DBNAME_CUSTOMER 1
38 #define DBNAME_ORDER 2
39 #define DBNAME_C2O 3 /* C2O: Customer To Order */
40 
41 #define DBIDX_CUSTOMER 0
42 #define DBIDX_ORDER 1
43 #define DBIDX_C2O 2
44 
45 #define MAX_CUSTOMERS 4
46 #define MAX_ORDERS 8
47 
48 /* A structure for the "customer" database */
49 typedef struct {
50  uint32_t id; /* customer id; will be the key of the customer table */
51  char name[32]; /* customer name */
52  /* ... additional information could follow here */
53 } customer_t;
54 
55 /* A structure for the "orders" database */
56 typedef struct {
57  uint32_t id; /* order id; will be the key of the order table */
58  uint32_t customer_id;/* customer id */
59  char assignee[32]; /* assigned to whom? */
60  /* ... additional information could follow here */
61 } order_t;
62 
63 int
64 main(int argc, char **argv) {
65  int i;
66  ups_status_t st; /* status variable */
67  ups_db_t *db[MAX_DBS]; /* upscaledb database objects */
68  ups_env_t *env; /* upscaledb environment */
69  ups_cursor_t *cursor[MAX_DBS]; /* a cursor for each database */
70  ups_key_t key = {0};
71  ups_key_t cust_key = {0};
72  ups_key_t ord_key = {0};
73  ups_key_t c2o_key = {0};
74  ups_record_t record = {0};
75  ups_record_t cust_record = {0};
76  ups_record_t ord_record = {0};
77  ups_record_t c2o_record = {0};
78 
79  ups_parameter_t params[] = {
81  {0, }
82  };
83 
84  ups_parameter_t c2o_params[] = {
87  {0, }
88  };
89 
90  customer_t customers[MAX_CUSTOMERS] = {
91  { 1, "Alan Antonov Corp." },
92  { 2, "Barry Broke Inc." },
93  { 3, "Carl Caesar Lat." },
94  { 4, "Doris Dove Brd." }
95  };
96 
97  order_t orders[MAX_ORDERS] = {
98  { 1, 1, "Joe" },
99  { 2, 1, "Tom" },
100  { 3, 3, "Joe" },
101  { 4, 4, "Tom" },
102  { 5, 3, "Ben" },
103  { 6, 3, "Ben" },
104  { 7, 4, "Chris" },
105  { 8, 1, "Ben" }
106  };
107 
108  /* Now create a new database file for the Environment */
109  st = ups_env_create(&env, "test.db", 0, 0664, 0);
110  if (st != UPS_SUCCESS)
111  error("ups_env_create", st);
112 
113  /*
114  * Then create the two Databases in this Environment; each Database
115  * has a name - the first is our "customer" Database, the second
116  * is for the "orders"; the third manages our 1:n relation and
117  * therefore needs to enable duplicate keys
118  */
120  0, &params[0]);
121  if (st != UPS_SUCCESS)
122  error("ups_env_create_db(customer)", st);
123  st = ups_env_create_db(env, &db[DBIDX_ORDER], DBNAME_ORDER, 0, &params[0]);
124  if (st != UPS_SUCCESS)
125  error("ups_env_create_db(order)", st);
126  st = ups_env_create_db(env, &db[DBIDX_C2O], DBNAME_C2O,
127  UPS_ENABLE_DUPLICATE_KEYS, &c2o_params[0]);
128  if (st != UPS_SUCCESS)
129  error("ups_env_create_db(c2o)", st);
130 
131  /* Create a Cursor for each Database */
132  for (i = 0; i < MAX_DBS; i++) {
133  st = ups_cursor_create(&cursor[i], db[i], 0, 0);
134  if (st != UPS_SUCCESS)
135  error("ups_cursor_create" , st);
136  }
137 
138  /*
139  * Insert the customers in the customer table
140  *
141  * INSERT INTO customers VALUES (1, "Alan Antonov Corp.");
142  * INSERT INTO customers VALUES (2, "Barry Broke Inc.");
143  * etc
144  */
145  for (i = 0; i < MAX_CUSTOMERS; i++) {
146  key.size = sizeof(int);
147  key.data = &customers[i].id;
148 
149  record.size = sizeof(customer_t);
150  record.data = &customers[i];
151 
152  st = ups_db_insert(db[0], 0, &key, &record, 0);
153  if (st != UPS_SUCCESS)
154  error("ups_db_insert (customer)", st);
155  }
156 
157  /*
158  * And now the orders in the second Database; contrary to env1,
159  * we only store the assignee, not the whole structure
160  *
161  * INSERT INTO orders VALUES (1, "Joe");
162  * INSERT INTO orders VALUES (2, "Tom");
163  */
164  for (i = 0; i < MAX_ORDERS; i++) {
165  key.size = sizeof(int);
166  key.data = &orders[i].id;
167 
168  record.size = sizeof(orders[i].assignee);
169  record.data = orders[i].assignee;
170 
171  st = ups_db_insert(db[1], 0, &key, &record, 0);
172  if (st != UPS_SUCCESS)
173  error("ups_db_insert (order)", st);
174  }
175 
176  /*
177  * And now the 1:n relationships; the flag UPS_DUPLICATE creates
178  * a duplicate key, if the key already exists
179  *
180  * INSERT INTO c2o VALUES (1, 1);
181  * INSERT INTO c2o VALUES (2, 1);
182  * etc
183  */
184  for (i = 0; i < MAX_ORDERS; i++) {
185  key.size = sizeof(int);
186  key.data = &orders[i].customer_id;
187 
188  record.size = sizeof(int);
189  record.data = &orders[i].id;
190 
191  st = ups_db_insert(db[2], 0, &key, &record, UPS_DUPLICATE);
192  if (st != UPS_SUCCESS)
193  error("ups_db_insert(c2o)", st);
194  }
195 
196  /*
197  * Now start the query - we want to dump each customer with his
198  * orders
199  *
200  * loop over the customer; for each customer, loop over the 1:n table
201  * and pick those orders with the customer id. then load the order
202  * and print it
203  *
204  * the outer loop is similar to:
205  * SELECT * FROM customers WHERE 1;
206  */
207  while (1) {
208  customer_t *customer;
209 
210  st = ups_cursor_move(cursor[0], &cust_key, &cust_record, UPS_CURSOR_NEXT);
211  if (st != UPS_SUCCESS) {
212  /* reached end of the database? */
213  if (st == UPS_KEY_NOT_FOUND)
214  break;
215  else
216  error("ups_cursor_next(customer)", st);
217  }
218 
219  customer = (customer_t *)cust_record.data;
220 
221  /* print the customer id and name */
222  printf("customer %d ('%s')\n", customer->id, customer->name);
223 
224  /*
225  * loop over the 1:n table
226  *
227  * before we start the loop, we move the cursor to the
228  * first duplicate key
229  *
230  * SELECT * FROM customers, orders, c2o
231  * WHERE c2o.customer_id=customers.id AND
232  * c2o.order_id=orders.id;
233  */
234  c2o_key.data = &customer->id;
235  c2o_key.size = sizeof(int);
236  st = ups_cursor_find(cursor[2], &c2o_key, 0, 0);
237  if (st != UPS_SUCCESS) {
238  if (st == UPS_KEY_NOT_FOUND)
239  continue;
240  error("ups_cursor_find(c2o)", st);
241  }
242  st = ups_cursor_move(cursor[2], 0, &c2o_record, 0);
243  if (st != UPS_SUCCESS)
244  error("ups_cursor_move(c2o)", st);
245 
246  do {
247  int order_id;
248 
249  order_id = *(int *)c2o_record.data;
250  ord_key.data = &order_id;
251  ord_key.size = sizeof(int);
252 
253  /*
254  * load the order
255  * SELECT * FROM orders WHERE id = order_id;
256  */
257  st = ups_db_find(db[1], 0, &ord_key, &ord_record, 0);
258  if (st != UPS_SUCCESS)
259  error("ups_db_find(order)", st);
260 
261  printf(" order: %d (assigned to %s)\n",
262  order_id, (char *)ord_record.data);
263 
264  /*
265  * The flag UPS_ONLY_DUPLICATES restricts the cursor
266  * movement to the duplicate list.
267  */
268  st = ups_cursor_move(cursor[2], &c2o_key,
269  &c2o_record, UPS_CURSOR_NEXT|UPS_ONLY_DUPLICATES);
270  if (st != UPS_SUCCESS) {
271  /* reached end of the database? */
272  if (st == UPS_KEY_NOT_FOUND)
273  break;
274  else
275  error("ups_cursor_next(c2o)", st);
276  }
277  } while (1);
278  }
279 
280  /*
281  * Now close the Environment handle; the flag
282  * UPS_AUTO_CLEANUP will automatically close all Databases and
283  * Cursors
284  */
285  st = ups_env_close(env, UPS_AUTO_CLEANUP);
286  if (st != UPS_SUCCESS)
287  error("ups_env_close", st);
288 
289  printf("success!\n");
290  return (0);
291 }
#define DBNAME_C2O
Definition: env2.c:39
#define MAX_DBS
Definition: env2.c:35
UPS_EXPORT const char *UPS_CALLCONV ups_strerror(ups_status_t status)
#define DBNAME_ORDER
Definition: env2.c:38
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_close(ups_env_t *env, uint32_t flags)
UPS_EXPORT ups_status_t UPS_CALLCONV ups_db_insert(ups_db_t *db, ups_txn_t *txn, ups_key_t *key, ups_record_t *record, uint32_t flags)
UPS_EXPORT ups_status_t UPS_CALLCONV ups_db_find(ups_db_t *db, ups_txn_t *txn, ups_key_t *key, ups_record_t *record, uint32_t flags)
#define MAX_CUSTOMERS
Definition: env2.c:45
#define UPS_TYPE_UINT32
Definition: upscaledb.h:322
UPS_EXPORT ups_status_t UPS_CALLCONV ups_cursor_move(ups_cursor_t *cursor, ups_key_t *key, ups_record_t *record, uint32_t flags)
char assignee[32]
Definition: env1.c:53
unsigned int uint32_t
Definition: msstdint.h:85
#define DBNAME_CUSTOMER
Definition: env2.c:37
Include file for upscaledb embedded database.
uint16_t size
Definition: upscaledb.h:255
UPS_EXPORT ups_status_t UPS_CALLCONV ups_cursor_find(ups_cursor_t *cursor, ups_key_t *key, ups_record_t *record, uint32_t flags)
#define DBIDX_CUSTOMER
Definition: env2.c:41
char name[32]
Definition: env1.c:45
#define DBIDX_ORDER
Definition: env2.c:42
#define UPS_PARAM_RECORD_SIZE
Definition: upscaledb.h:1725
uint32_t id
Definition: env1.c:44
struct ups_db_t ups_db_t
Definition: upscaledb.h:156
#define UPS_CURSOR_NEXT
Definition: upscaledb.h:2051
struct ups_cursor_t ups_cursor_t
Definition: upscaledb.h:177
#define MAX_ORDERS
Definition: env2.c:46
#define UPS_AUTO_CLEANUP
Definition: upscaledb.h:1883
#define UPS_ONLY_DUPLICATES
Definition: upscaledb.h:2060
#define UPS_ENABLE_DUPLICATE_KEYS
Definition: upscaledb.h:1309
#define UPS_SUCCESS
Definition: upscaledb.h:341
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_create(ups_env_t **env, const char *filename, uint32_t flags, uint32_t mode, const ups_parameter_t *param)
void * data
Definition: upscaledb.h:258
uint32_t customer_id
Definition: env1.c:52
#define UPS_DUPLICATE
Definition: upscaledb.h:1566
int main(int argc, char **argv)
Definition: env2.c:64
Definition: env1.c:50
void * data
Definition: upscaledb.h:207
uint32_t size
Definition: upscaledb.h:204
int ups_status_t
Definition: types.h:139
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_create_db(ups_env_t *env, ups_db_t **db, uint16_t name, uint32_t flags, const ups_parameter_t *params)
void error(const char *foo, ups_status_t st)
Definition: env2.c:30
#define UPS_PARAM_KEY_TYPE
Definition: upscaledb.h:1710
#define DBIDX_C2O
Definition: env2.c:43
uint32_t id
Definition: env1.c:51
UPS_EXPORT ups_status_t UPS_CALLCONV ups_cursor_create(ups_cursor_t **cursor, ups_db_t *db, ups_txn_t *txn, uint32_t flags)
#define UPS_KEY_NOT_FOUND
Definition: upscaledb.h:361
struct ups_env_t ups_env_t
Definition: upscaledb.h:165