Add -a append option to mdb_load

To allow reloading of custom-sorted DBs from mdb_dump
This commit is contained in:
Howard Chu 2017-09-20 18:41:11 +01:00
parent 1a73843cec
commit 2540d162be
No known key found for this signature in database
GPG key ID: FD2A70B44AB11BA7
2 changed files with 47 additions and 6 deletions

View file

@ -37,6 +37,13 @@ option below.
.BR \-V .BR \-V
Write the library version number to the standard output, and exit. Write the library version number to the standard output, and exit.
.TP .TP
.BR \-a
Append all records in the order they appear in the input. The input is assumed to already be
in correctly sorted order and no sorting or checking for redundant values will be performed.
This option must be used to reload data that was produced by running
.B mdb_dump
on a database that uses custom compare functions.
.TP
.BR \-f \ file .BR \-f \ file
Read from the specified file instead of from the standard input. Read from the specified file instead of from the standard input.
.TP .TP

View file

@ -37,6 +37,7 @@ static int Eof;
static MDB_envinfo info; static MDB_envinfo info;
static MDB_val kbuf, dbuf; static MDB_val kbuf, dbuf;
static MDB_val k0buf;
#ifdef _WIN32 #ifdef _WIN32
#define Z "I" #define Z "I"
@ -285,10 +286,15 @@ badend:
static void usage(void) static void usage(void)
{ {
fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog); fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
static int greater(const MDB_val *a, const MDB_val *b)
{
return 1;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i, rc; int i, rc;
@ -298,7 +304,8 @@ int main(int argc, char *argv[])
MDB_dbi dbi; MDB_dbi dbi;
char *envname; char *envname;
int envflags = 0, putflags = 0; int envflags = 0, putflags = 0;
int dohdr = 0; int dohdr = 0, append = 0;
MDB_val prevk;
prog = argv[0]; prog = argv[0];
@ -306,19 +313,23 @@ int main(int argc, char *argv[])
usage(); usage();
} }
/* -f: load file instead of stdin /* -a: append records in input order
* -f: load file instead of stdin
* -n: use NOSUBDIR flag on env_open * -n: use NOSUBDIR flag on env_open
* -s: load into named subDB * -s: load into named subDB
* -N: use NOOVERWRITE on puts * -N: use NOOVERWRITE on puts
* -T: read plaintext * -T: read plaintext
* -V: print version and exit * -V: print version and exit
*/ */
while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) { while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) {
switch(i) { switch(i) {
case 'V': case 'V':
printf("%s\n", MDB_VERSION_STRING); printf("%s\n", MDB_VERSION_STRING);
exit(0); exit(0);
break; break;
case 'a':
append = 1;
break;
case 'f': case 'f':
if (freopen(optarg, "r", stdin) == NULL) { if (freopen(optarg, "r", stdin) == NULL) {
fprintf(stderr, "%s: %s: reopen: %s\n", fprintf(stderr, "%s: %s: reopen: %s\n",
@ -377,12 +388,17 @@ int main(int argc, char *argv[])
} }
kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2; kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
kbuf.mv_data = malloc(kbuf.mv_size); kbuf.mv_data = malloc(kbuf.mv_size * 2);
k0buf.mv_size = kbuf.mv_size;
k0buf.mv_data = (char *)kbuf.mv_data + kbuf.mv_size;
prevk.mv_size = 0;
prevk.mv_data = k0buf.mv_data;
while(!Eof) { while(!Eof) {
MDB_val key, data; MDB_val key, data;
int batch = 0; int batch = 0;
flags = 0; flags = 0;
int appflag;
if (!dohdr) { if (!dohdr) {
dohdr = 1; dohdr = 1;
@ -400,6 +416,11 @@ int main(int argc, char *argv[])
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
goto txn_abort; goto txn_abort;
} }
if (append) {
mdb_set_compare(txn, dbi, greater);
if (flags & MDB_DUPSORT)
mdb_set_dupsort(txn, dbi, greater);
}
rc = mdb_cursor_open(txn, dbi, &mc); rc = mdb_cursor_open(txn, dbi, &mc);
if (rc) { if (rc) {
@ -418,7 +439,20 @@ int main(int argc, char *argv[])
goto txn_abort; goto txn_abort;
} }
rc = mdb_cursor_put(mc, &key, &data, putflags); if (append) {
appflag = MDB_APPEND;
if (flags & MDB_DUPSORT) {
if (prevk.mv_size == key.mv_size && !memcmp(prevk.mv_data, key.mv_data, key.mv_size))
appflag = MDB_APPENDDUP;
else {
memcpy(prevk.mv_data, key.mv_data, key.mv_size);
prevk.mv_size = key.mv_size;
}
}
} else {
appflag = 0;
}
rc = mdb_cursor_put(mc, &key, &data, putflags|appflag);
if (rc == MDB_KEYEXIST && putflags) if (rc == MDB_KEYEXIST && putflags)
continue; continue;
if (rc) { if (rc) {