plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

commit 69cf5e2d79b53afa6774e05c3b12629bbb38fbab
parent 451499435c91584a1f9f75910aaf29914b7034f4
Author: ssnf <ssnf@ssnf.xyz>
Date:   Thu, 10 Jul 2025 04:06:22 -0500

port sdb tools

Diffstat:
M.gitignore | 7+++++++
Minclude/str.h | 2++
Asrc/cmd/sdb/mkfile | 17+++++++++++++++++
Asrc/cmd/sdb/sdbedit.c | 36++++++++++++++++++++++++++++++++++++
Asrc/cmd/sdb/sdbjoin.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/sdb/sdbmap.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/sdb/sdbpretty.c | 38++++++++++++++++++++++++++++++++++++++
Asrc/cmd/sdb/sdbquery.c | 37+++++++++++++++++++++++++++++++++++++
Asrc/cmd/sdb/sdbrval.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/sdb/sdbuniq.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/sdb/std.h | 7+++++++
11 files changed, 431 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -170,6 +170,13 @@ bin/rsagen bin/sam bin/samterm bin/scat +bin/sdbedit +bin/sdbjoin +bin/sdbmap +bin/sdbpretty +bin/sdbquery +bin/sdbrval +bin/sdbuniq bin/secstore bin/secstored bin/secuser diff --git a/include/str.h b/include/str.h @@ -1,3 +1,5 @@ +AUTOLIB(str) + #define STRSIZ 2 typedef unsigned long Posn; diff --git a/src/cmd/sdb/mkfile b/src/cmd/sdb/mkfile @@ -0,0 +1,17 @@ +<$PLAN9/src/mkhdr + +TARG=\ + sdbedit\ + sdbjoin\ + sdbmap\ + sdbpretty\ + sdbquery\ + sdbrval\ + sdbuniq\ + +HFILES=\ + $PLAN9/include/sdbr.h\ + $PLAN9/include/sdb.h\ + std.h\ + +<$PLAN9/src/mkmany diff --git a/src/cmd/sdb/sdbedit.c b/src/cmd/sdb/sdbedit.c @@ -0,0 +1,36 @@ +#include "std.h" + +static char *file; + +static void +usage(void) +{ + fprint(2, "sdbedit: [-f file] attr0 value0 [attr1 value1]..."); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + Sdb db; + Sdbr q, r; + + ARGBEGIN { + case 'f': + file = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + if (argc < 2) + usage(); + sdbr_init(&q); + sdbr_init(&r); + sdbr_add(&q, Str(argv[0]), Str(argv[1])); + sdbr_arg2r(&r, &argv[2]); + sdb_open(&db, file); + sdb_edit(&db, q, r); + sdb_flush(&db); + sdb_close(&db); + exits(0); +} diff --git a/src/cmd/sdb/sdbjoin.c b/src/cmd/sdb/sdbjoin.c @@ -0,0 +1,50 @@ +#include "std.h" + +static char *file[2]; + +static void +usage(void) +{ + fprint(2, "sdbjoin: [-f file0] file1 [attr [val]]...\n"); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + Sdb db[2]; + Sdbr r, *sr; + ulong i; + + ARGBEGIN { + case 'f': + file[0] = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + if (argc < 1) + usage(); + file[1] = *argv; + sdbr_init(&r); + sdbr_add(&r, Str(""), Str("")); + sdbr_arg2r(&r, &argv[1]); + sdb_open(&db[0], file[0]); + sdb_open(&db[1], file[1]); + for (;sdb_next(&db[0]);) { + sr = db[0].r + db[0].n; + Strinsert(&r.attr[0], sr->attr[0], 0); + Strinsert(&r.val[0], sr->val[0], 0); + for (;sdb_query(&db[1], r);) { + vsdbr_join(&db[0].r, db[1].r[db[1].n]); + if (!sdb_next(&db[1])) + break; + } + Strzero(&r.attr[0]); + Strzero(&r.val[0]); + sdb_rewind(&db[1]); + } + for (i = 0; i < sdb_n(db[0]); ++i) + sdbr_print(db[0].r[i]); + exits(0); +} diff --git a/src/cmd/sdb/sdbmap.c b/src/cmd/sdb/sdbmap.c @@ -0,0 +1,58 @@ +#include "std.h" + +static void usage(void); + +static char* file; +static char* key; + +static void +usage(void) +{ + fprint(2, "sdbmap: [-k attr] [-f file0] file attr0 attr1\n"); + exits("usage"); +} + +void +main(int argc, char* argv[]) +{ + Sdb db, map; + Sdbr r; + String p; + + ARGBEGIN { + case 'f': + file = EARGF(usage()); + break; + case 'k': + key = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + if (argc < 3) + usage(); + sdb_open(&db, file); + sdb_open(&map, *argv++); + if (!key) + key = argv[0]; + sdbr_init(&r); + for (;sdb_next(&db);) { + p = sdbr_val(db.r[db.n], argv[0]); + if (!p.s) + goto print; + sdb_rewind(&map); + sdbr_zero(&r); + sdbr_add(&r, Str(key), p); + if (!sdb_query(&map, r)) + goto print; + p = sdbr_val(map.r[map.n], argv[1]); + if (!p.s) + goto print; + sdbr_zero(&r); + sdbr_add(&r, Str(argv[0]), p); + sdbr_edit(db.r + db.n, r); +print: + sdbr_print(db.r[db.n]); + } + exits(0); +} diff --git a/src/cmd/sdb/sdbpretty.c b/src/cmd/sdb/sdbpretty.c @@ -0,0 +1,38 @@ +#include "std.h" + +static char* file; + +static void +usage(void) +{ + fprint(2, "sdbpretty: [-f file]\n"); + exits("usage"); +} + +void +main(int argc, char* argv[]) +{ + Sdb db; + Sdbr r; + String s; + ulong i; + + ARGBEGIN { + case 'f': + file = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + sdb_open(&db, file); + Strinit(&s); + for (;sdb_next(&db);) { + r = db.r[db.n]; + print("%s=%s\n", r.attr[0].s + , sdbr_escape(&s, r.val[0])); + for (i = 1; i < sdbr_n(r); ++i) + print("\t%s=%s\n", r.attr[i].s + , sdbr_escape(&s, r.val[i])); + } + exits(0); +} diff --git a/src/cmd/sdb/sdbquery.c b/src/cmd/sdb/sdbquery.c @@ -0,0 +1,37 @@ +#include "std.h" + +static char *file; + +static void +usage(void) +{ + fprint(2, "sdbquery: " + "[-f file] attr0 value0 [attr1 value1]...\n"); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + Sdbr q; + Sdb db; + + ARGBEGIN { + case 'f': + file = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + if (argc < 2) + usage(); + sdbr_init(&q); + sdbr_arg2r(&q, argv); + sdb_open(&db, file); + for (;sdb_query(&db, q);) { + sdbr_print(db.r[db.n]); + if (!sdb_next(&db)) + break; + } + exits(0); +} diff --git a/src/cmd/sdb/sdbrval.c b/src/cmd/sdb/sdbrval.c @@ -0,0 +1,74 @@ +#include "std.h" + +static void print_col(Sdbr*, char*); + +static String val; +static char *fmt = "%.0s%s"; +static void (*print_fn)(Sdbr*, char*) = print_col; + +static void +print_col(Sdbr *r, char *attr) +{ + int n; + + n = sdbr_attr(*r, attr); + if (n < 0) { + print(fmt, attr, ""); + return; + } + sdbr_escape(&val, r->val[n]); + print(fmt, r->attr[n].s, val.s); +} + +static void +print_match(Sdbr *r, char *attr) +{ + ulong i; + + for (i = 0; i < sdbr_n(*r); ++i) { + if (!sdbr_match(attr, r->attr[i].s)) + continue; + sdbr_escape(&val, r->val[i]); + print(fmt, r->attr[i].s, val.s); + } +} + +static void +usage(void) +{ + fprint(2, "sdbrval: [-am] attr ...\n"); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + Sdb db; + Sdbr *r; + ulong n; + + ARGBEGIN { + case 'a': + fmt = "%s=%s"; + break; + case 'm': + print_fn = print_match; + break; + default: + usage(); + } ARGEND; + if (argc < 1) + usage(); + Strinit(&val); + sdb_open(&db, nil); + for (;sdb_next(&db);) { + r = db.r + db.n; + print_fn(r, argv[0]); + for (n = 1; n < argc; ++n) { + write(1, "\t", 1); + print_fn(r, argv[n]); + } + write(1, "\n", 1); + } + exits(0); +} diff --git a/src/cmd/sdb/sdbuniq.c b/src/cmd/sdb/sdbuniq.c @@ -0,0 +1,105 @@ +#include "std.h" + +static char *file; +static char *key[256]; + +static int +iskey(char *attr) +{ + ulong i; + + for (i = 0; key[i]; ++i) + if (!strcmp(attr, key[i])) + return 1; + return 0; +} + +static int +isnew(Sdbr r0, Sdbr r1, char *attr) +{ + String val[2]; + + val[0] = sdbr_val(r0, attr); + val[1] = sdbr_val(r1, attr); + if (!val[1].s + || (val[0].s && !strcmp(val[0].s, val[1].s)) + ) + return 0; + return 1; +} + +static void +usage(void) +{ + fprint(2, "sdbuniq: [-f file] [attr]...\n"); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + Sdb db; + Sdbr r, cr, nr, *sr; + char *attr; + ulong i, nk; + + ARGBEGIN { + case 'f': + file = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + for (nk = 0; *argv; ++nk) + key[nk] = *argv++; + sdbr_init(&cr); + sdbr_init(&nr); + sdbr_init(&r); + sdb_open(&db, file); + sdb_next(&db); + sdbr_dup(&cr, db.r[db.n]); + sdbr_dup(&nr, db.r[db.n]); + for (;sdb_next(&db);) { + sr = db.r + db.n; + /* first attribute is always a key, regardless of name */ + if (strcmp(sr->val[0].s, cr.val[0].s)) { + if (sdbr_n(nr) > nk + 1) + sdbr_print(nr); + sdbr_dup(&cr, *sr); + sdbr_dup(&nr, *sr); + continue; + } + /* + * check each key for changes and update internal + * current record (cr) state + */ + for (i = 0; i < nk; ++i) { + if (!isnew(cr, *sr, key[i])) + continue; + if (sdbr_n(nr) > nk + 1) + sdbr_print(nr); + sdbr_zero(&nr); + sdbr_add(&nr, cr.attr[0], cr.val[0]); + for (i = 0; i < nk; ++i) + sdbr_add(&nr, Str(key[i]) + , sdbr_val(*sr, key[i]) + ); + sdbr_edit(&cr, nr); + break; + } + for (i = 1; i < sdbr_n(*sr); ++i) { + attr = sr->attr[i].s; + if (iskey(attr) || !isnew(cr, *sr, attr)) + continue; + sdbr_add(&r, Str(attr), sdbr_val(*sr, attr)); + } + if (sdbr_n(r)) { + sdbr_edit(&cr, r); + sdbr_edit(&nr, r); + sdbr_zero(&r); + } + } + if (sdbr_n(nr) > nk + 1) + sdbr_print(nr); + exits(0); +} diff --git a/src/cmd/sdb/std.h b/src/cmd/sdb/std.h @@ -0,0 +1,7 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <str.h> +#include <vec.h> +#include <sdbr.h> +#include <sdb.h>