mirror of
https://gitflic.ru/project/erthink/libmdbx.git
synced 2025-01-24 17:16:06 +00:00
mdbx-test: добавление extra/upsert_alldups
.
This commit is contained in:
parent
da4e2ab254
commit
04ed388761
@ -64,9 +64,13 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT SUBPROJECT)
|
||||
add_executable(pcrf_test pcrf/pcrf_test.c)
|
||||
target_include_directories(pcrf_test PRIVATE "${PROJECT_SOURCE_DIR}")
|
||||
target_link_libraries(pcrf_test ${TOOL_MDBX_LIB})
|
||||
add_executable(test_extra_pcrf extra/pcrf/pcrf_test.c)
|
||||
target_include_directories(test_extra_pcrf PRIVATE "${PROJECT_SOURCE_DIR}")
|
||||
target_link_libraries(test_extra_pcrf ${TOOL_MDBX_LIB})
|
||||
|
||||
add_executable(test_extra_upsert_alldups extra/upsert_alldups.c)
|
||||
target_include_directories(test_extra_upsert_alldups PRIVATE "${PROJECT_SOURCE_DIR}")
|
||||
target_link_libraries(test_extra_upsert_alldups ${TOOL_MDBX_LIB})
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
|
195
test/extra/upsert_alldups.c
Normal file
195
test/extra/upsert_alldups.c
Normal file
@ -0,0 +1,195 @@
|
||||
//
|
||||
// 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 = {};
|
||||
MDBX_val data = {};
|
||||
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 = {};
|
||||
MDBX_val data = {};
|
||||
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_COALESCE | 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;
|
||||
}
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user