libmdbx/test/extra/upsert_alldups.c
2024-04-04 15:00:27 +03:00

195 lines
5.7 KiB
C

//
// libmdbx/test/extra/upsert_alldups.c
//
// Created by Masatoshi Fukunaga <https://gitflic.ru/user/mah0x211>
// on 2023-01-31.
//
#include "mdbx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int dump(MDBX_cursor *cur) {
MDBX_val key = {NULL, 0};
MDBX_val data = {NULL, 0};
int rc = mdbx_cursor_get(cur, &key, &data, MDBX_FIRST);
while (rc == 0) {
printf("(%.*s) = (%.*s)\n", (int)key.iov_len, (const char *)key.iov_base,
(int)data.iov_len, (const char *)data.iov_base);
rc = mdbx_cursor_get(cur, &key, &data, MDBX_NEXT);
}
return rc;
}
static int clear(MDBX_cursor *cur) {
MDBX_val key = {NULL, 0};
MDBX_val data = {NULL, 0};
int rc = mdbx_cursor_get(cur, &key, &data, MDBX_FIRST);
while (rc == 0) {
rc = mdbx_cursor_del(cur, MDBX_ALLDUPS);
if (rc)
return rc;
rc = mdbx_cursor_get(cur, &key, &data, MDBX_NEXT);
}
return (rc == MDBX_NOTFOUND) ? 0 : rc;
}
static int put(MDBX_txn *txn, MDBX_dbi dbi, const char *k, const char *v,
MDBX_put_flags_t flags) {
MDBX_val key = {.iov_base = (void *)k, .iov_len = strlen(k)};
MDBX_val data = {.iov_base = (void *)v, .iov_len = strlen(v)};
return mdbx_put(txn, dbi, &key, &data, flags);
}
int main(int argc, const char *argv[]) {
(void)argc;
(void)argv;
char *errmsg = NULL;
MDBX_env *env = NULL;
MDBX_txn *txn = NULL;
MDBX_cursor *cur = NULL;
MDBX_dbi dbi = 0;
unlink("." MDBX_DATANAME);
unlink("." MDBX_LOCKNAME);
int rc = 0;
if ((rc = mdbx_env_create(&env))) {
errmsg = "failed to mdbx_env_create: %s\n";
goto Fail;
}
if ((rc = mdbx_env_open(env, ".", MDBX_NOSUBDIR | MDBX_LIFORECLAIM, 0644))) {
errmsg = "failed to mdbx_env_open: %s\n";
goto Fail;
}
if ((rc = mdbx_txn_begin(env, NULL, 0, &txn))) {
errmsg = "failed to mdbx_txn_begin: %s\n";
goto Fail;
}
if ((rc = mdbx_dbi_open(txn, NULL, MDBX_DUPSORT | MDBX_CREATE, &dbi))) {
errmsg = "failed to mdbx_dbi_open: %s\n";
goto Fail;
}
if ((rc = mdbx_cursor_open(txn, dbi, &cur))) {
errmsg = "failed to mdbx_cursor_open: %s\n";
goto Fail;
}
#define DUMP() \
do { \
if ((rc = dump(cur)) && rc != MDBX_NOTFOUND) { \
errmsg = "failed to mdbx_cursor_get(FIRST): %s\n"; \
goto Fail; \
} \
puts(""); \
} while (0)
#define PUTVAL(k, v, flags) \
do { \
if ((rc = put(txn, dbi, k, v, flags))) { \
errmsg = "failed to mdbx_put: %s\n"; \
goto Fail; \
} \
} while (0)
puts("TEST WITH MULTIPLE KEYS ====================");
// UPSERTING
// MDBX_UPSERT:
// Key is absent → Insertion (Insertion)
// Key exist → Wanna to add new values (Overwrite by single new value)
puts("insert multiple keys and values {");
puts(" foo = bar, baz, qux");
puts(" hello = world");
puts("}");
PUTVAL("foo", "bar", MDBX_UPSERT);
PUTVAL("foo", "baz", MDBX_UPSERT);
PUTVAL("foo", "qux", MDBX_UPSERT);
PUTVAL("hello", "world", MDBX_UPSERT);
DUMP();
//
// above code will output the fllowing;
//
// insert multiple values {
// foo = bar, baz, qux
// hello = world
// }
// (foo) = (bar)
// (foo) = (baz)
// (foo) = (qux)
// (hello) = (world)
//
// UPSERTING
// MDBX_UPSERT + MDBX_ALLDUPS:
// Key exist → Replace all values with a new one (Overwrite by single new
// value)
puts("overwrite by single new value: MDBX_UPSERT + MDBX_ALLDUPS {");
puts(" foo = baa");
puts("}");
PUTVAL("foo", "baa", MDBX_UPSERT | MDBX_ALLDUPS);
DUMP();
// above code will output the fllowing;
// overwrite by single new value {
// foo = baa
// }
// (foo) = (baa)
// (hello) = (world)
if ((rc = clear(cur))) {
errmsg = "failed to clear: %s\n";
goto Fail;
}
DUMP();
puts("TEST WITH A SINGLE KEY ====================");
// UPSERTING
// MDBX_UPSERT:
// Key is absent → Insertion (Insertion)
// Key exist → Wanna to add new values (Overwrite by single new value)
puts("insert single key and multiple values {");
puts(" foo = bar, baz, qux");
puts("}");
PUTVAL("foo", "bar", MDBX_UPSERT);
PUTVAL("foo", "baz", MDBX_UPSERT);
PUTVAL("foo", "qux", MDBX_UPSERT);
DUMP();
//
// above code will output the fllowing;
//
// insert: foo = bar, baz, qux
// foo = bar
// foo = baz
// foo = qux
// UPSERTING
// MDBX_UPSERT + MDBX_ALLDUPS:
// Key exist → Replace all values with a new one (Overwrite by single new
// value)
puts("overwrite by single new value: MDBX_UPSERT + MDBX_ALLDUPS {");
puts(" foo = baa");
puts("}");
PUTVAL("foo", "baa", MDBX_UPSERT | MDBX_ALLDUPS);
DUMP();
// above code outputs nothing.
// all data associated with key has been deleted.
// Is it a bug? Or, am I misunderstanding how to use it?
if ((rc = mdbx_txn_commit(txn))) {
errmsg = "failed to mdbx_txn_commit: %s\n";
goto Fail;
}
mdbx_cursor_close(cur);
if ((rc = mdbx_env_close(env))) {
errmsg = "failed to mdbx_env_close: %s\n";
goto Fail;
}
return 0;
Fail:
printf(errmsg, mdbx_strerror(rc));
return EXIT_FAILURE;
}