mdbx-tools: добавление опции -c (concise) в mdbx_dump.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2025-03-16 20:02:26 +03:00
parent ef9fd1f3fb
commit db44f4ed71
3 changed files with 48 additions and 39 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;