diff --git a/src/man1/mdbx_dump.1 b/src/man1/mdbx_dump.1 index 6b04c0af..39e917ce 100644 --- a/src/man1/mdbx_dump.1 +++ b/src/man1/mdbx_dump.1 @@ -12,6 +12,8 @@ mdbx_dump \- MDBX environment export tool [\c .BR \-q ] [\c +.BR \-c ] +[\c .BI \-f \ file\fR] [\c .BR \-l ] @@ -41,6 +43,9 @@ Write the library version number to the standard output, and exit. .BR \-q Be quiet. .TP +.BR \-c +Concise mode without repeating keys in a dump, but incompatible with Berkeley DB and LMDB. +.TP .BR \-f \ file Write to the specified file instead of to the standard output. .TP diff --git a/src/tools/dump.c b/src/tools/dump.c index c09b2b17..95d9c72b 100644 --- a/src/tools/dump.c +++ b/src/tools/dump.c @@ -20,6 +20,7 @@ #define PRINT 1 #define GLOBAL 2 +#define CONCISE 4 static int mode = GLOBAL; typedef struct flagbit { @@ -55,42 +56,23 @@ static void signal_handler(int sig) { #endif /* !WINDOWS */ -static const char hexc[] = "0123456789abcdef"; - -static void dumpbyte(unsigned char c) { - putchar(hexc[c >> 4]); - putchar(hexc[c & 15]); -} - -static void text(MDBX_val *v) { - unsigned char *c, *end; - +static void dumpval(const MDBX_val *v) { + static const char digits[] = "0123456789abcdef"; putchar(' '); - c = v->iov_base; - end = c + v->iov_len; - while (c < end) { - if (isprint(*c) && *c != '\\') { - putchar(*c); - } else { - putchar('\\'); - dumpbyte(*c); + for (const unsigned char *c = v->iov_base, *end = c + v->iov_len; c < end; ++c) { + if (mode & PRINT) { + if (isprint(*c) && *c != '\\') { + putchar(*c); + continue; + } else + putchar('\\'); } - c++; + putchar(digits[*c >> 4]); + putchar(digits[*c & 15]); } putchar('\n'); } -static void dumpval(MDBX_val *v) { - unsigned char *c, *end; - - putchar(' '); - c = v->iov_base; - end = c + v->iov_len; - while (c < end) - dumpbyte(*c++); - putchar('\n'); -} - bool quiet = false, rescue = false; const char *prog; static void error(const char *func, int rc) { @@ -185,12 +167,19 @@ static int dump_tbl(MDBX_txn *txn, MDBX_dbi dbi, char *name) { rc = MDBX_EINTR; break; } - if (mode & PRINT) { - text(&key); - text(&data); - } else { - dumpval(&key); - dumpval(&data); + dumpval(&key); + dumpval(&data); + if ((flags & MDBX_DUPSORT) && (mode & CONCISE)) { + while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT_DUP)) == MDBX_SUCCESS) { + if (user_break) { + rc = MDBX_EINTR; + break; + } + putchar(' '); + dumpval(&data); + } + if (rc != MDBX_NOTFOUND) + break; } } printf("DATA=END\n"); @@ -206,10 +195,12 @@ static int dump_tbl(MDBX_txn *txn, MDBX_dbi dbi, char *name) { static void usage(void) { fprintf(stderr, "usage: %s " - "[-V] [-q] [-f file] [-l] [-p] [-r] [-a|-s table] [-u|U] " + "[-V] [-q] [-c] [-f file] [-l] [-p] [-r] [-a|-s table] [-u|U] " "dbpath\n" " -V\t\tprint version and exit\n" " -q\t\tbe quiet\n" + " -c\t\tconcise mode without repeating keys,\n" + " \t\tbut incompatible with Berkeley DB and LMDB\n" " -f\t\twrite to file instead of stdout\n" " -l\t\tlist tables and exit\n" " -p\t\tuse printable characters\n" @@ -268,6 +259,7 @@ int main(int argc, char *argv[]) { "s:" "V" "r" + "c" "q")) != EOF) { switch (i) { case 'V': @@ -298,6 +290,9 @@ int main(int argc, char *argv[]) { break; case 'n': break; + case 'c': + mode |= CONCISE; + break; case 'p': mode |= PRINT; break; diff --git a/src/tools/load.c b/src/tools/load.c index 0220ce22..6cb35c60 100644 --- a/src/tools/load.c +++ b/src/tools/load.c @@ -380,7 +380,16 @@ __hot static int readline(MDBX_val *out, MDBX_val *buf) { return badend(); } } - if (fgets(buf->iov_base, (int)buf->iov_len, stdin) == nullptr) + + /* modern concise mode, where space in second position mean the same (previously) value */ + c = fgetc(stdin); + if (c == EOF) + return errno ? errno : EOF; + if (c == ' ') + return (ungetc(c, stdin) == c) ? MDBX_SUCCESS : (errno ? errno : EOF); + + *(char *)buf->iov_base = c; + if (fgets((char *)buf->iov_base + 1, (int)buf->iov_len - 1, stdin) == nullptr) return errno ? errno : EOF; lineno++; @@ -721,8 +730,8 @@ int main(int argc, char *argv[]) { } int batch = 0; + MDBX_val key = {.iov_base = nullptr, .iov_len = 0}, data = {.iov_base = nullptr, .iov_len = 0}; while (err == MDBX_SUCCESS) { - MDBX_val key, data; err = readline(&key, &kbuf); if (err == EOF) break;