• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ///
2 /// Compound keys demo.
3 ///
4 /// Compound keys allows associate one `key value` with many references
5 /// represented as VNUM64 (eg.: Non unique table indexes).
6 ///
7 /// Compound mainly used for non-unique indexes in ejdb2 database engine:
8 ///
9 ///   `<prefix key value>.<document id>`
10 ///
11 
12 #include "iwkv.h"
13 #include <string.h>
14 #include <stdlib.h>
15 #include <stdint.h>
16 
17 struct user_s {
18   uint32_t id;
19   char *name;
20 };
21 
22 struct chat_root_s {
23   char *name;
24   struct user_s users[5];
25 };
26 
27 static struct chat_root_s rooms[] = {
28   {
29     .name = "Meeting room",
30     .users = {
31       { .id = 1, .name = "Joy Lynn" },
32       { .id = 2, .name = "Aubrey Sparks" },
33       { .id = 3, .name = "Vinnie Kaye"},
34       { 0 }
35     }
36   },
37   {
38     .name = "Webinar room",
39     .users = {
40       { .id = 4, .name = "Arda Payne" },
41       { .id = 2, .name = "Joy Lynn" },
42       { 0 }
43     }
44   }
45 };
46 
run(void)47 static iwrc run(void) {
48   IWKV_OPTS opts = {
49     .path = "compoundkeys.db",
50     .oflags = IWKV_TRUNC
51   };
52   IWKV iwkv;
53   IWDB db;
54   IWKV_cursor cur = 0;
55   iwrc rc = iwkv_open(&opts, &iwkv);
56   RCRET(rc);
57 
58   rc = iwkv_db(iwkv, 1, IWDB_COMPOUND_KEYS, &db);
59   RCGO(rc, finish);
60 
61   // Persist all rooms with members
62   for (int i = 0; i < sizeof(rooms) / sizeof(rooms[0]); ++i) {
63     int j = 0;
64     struct chat_root_s *room = &rooms[i];
65     for (struct user_s *user = &room->users[0]; user->id; user = &room->users[++j]) {
66       IWKV_val key = { .data = room->name, .size = strlen(room->name), .compound = user->id };
67       IWKV_val val = { .data = user->name, .size = strlen(user->name) };
68       RCC(rc, finish, iwkv_put(db, &key, &val, 0));
69     }
70   }
71 
72   // Get specific user from the room
73   {
74     IWKV_val key = { .data = "Webinar room", .size = sizeof("Webinar room") - 1, .compound = 2 };
75     IWKV_val val;
76     RCC(rc, finish, iwkv_get(db, &key, &val));
77     fprintf(stdout, "\n>>>> Found: '%.*s' in room '%s' by id: %d\n",
78             (int) val.size, (char *) val.data,
79             (char *) key.data, (int) key.compound);
80     iwkv_val_dispose(&val);
81   }
82 
83   // Iterate over all members in `Meeting room`
84   {
85     size_t len = strlen(rooms[0].name);
86     fprintf(stdout, "\n>>>> Iterate over all members in %s\n", rooms[0].name);
87     IWKV_val val, key = { .data = rooms[0].name, .size = len };
88     RCC(rc, finish, iwkv_cursor_open(db, &cur, IWKV_CURSOR_GE, &key));
89     do {
90       RCC(rc, finish, iwkv_cursor_get(cur, &key, &val));
91       if (memcmp(key.data, rooms[0].name, MIN(key.size, len))) {
92         // We rolled to end of `Meeting room` room
93         iwkv_kv_dispose(&key, &val);
94         break;
95       }
96       fprintf(stdout, "%.*s: %d %.*s\n",
97               (int) key.size, (char *) key.data,
98               (int) key.compound,
99               (int) val.size,
100               (char *) val.data);
101       iwkv_kv_dispose(&key, &val);
102     } while ((rc = iwkv_cursor_to(cur, IWKV_CURSOR_PREV)) == 0);
103     rc = 0;
104   }
105 
106 finish:
107   if (cur) {
108     iwkv_cursor_close(&cur);
109   }
110   iwkv_close(&iwkv);
111   return rc;
112 }
113 
main()114 int main() {
115   iwrc rc = run();
116   if (rc) {
117     iwlog_ecode_error3(rc);
118     return 1;
119   }
120   return 0;
121 }
122