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(void)114 int main(void) {
115 iwrc rc = run();
116 if (rc) {
117 iwlog_ecode_error3(rc);
118 return 1;
119 }
120 return 0;
121 }
122