use super::util::{arr, bulk, err, int, kevy_err};
use crate::store::Store;
pub(super) fn dispatch(s: &Store, up: &[u8], argv: &[Vec<u8>], out: &mut Vec<u8>) -> bool {
match up {
b"TABLE.DECLARE" => cmd_declare(s, argv, out),
b"TABLE.DROP" => {
if argv.len() != 2 {
err(out, "ERR usage: TABLE.DROP name");
} else {
int(out, i64::from(s.table_drop(&argv[1])));
}
}
b"TABLE.LIST" => {
if argv.len() != 1 {
err(out, "ERR usage: TABLE.LIST");
} else {
cmd_list(s, out);
}
}
b"TABLE.VERIFY" => {
if argv.len() != 2 {
err(out, "ERR usage: TABLE.VERIFY name");
} else {
cmd_verify(s, &argv[1], out);
}
}
_ => return false,
}
true
}
fn cmd_declare(s: &Store, argv: &[Vec<u8>], out: &mut Vec<u8>) {
let refs: Vec<&[u8]> = argv.iter().map(Vec::as_slice).collect();
match kevy_index::parse_table_declare(&refs) {
Err(e) => err(out, &e),
Ok(spec) => match s.table_declare(spec) {
Ok(()) => out.extend_from_slice(b"+OK\r\n"),
Err(e) => kevy_err(out, &e),
},
}
}
fn cmd_list(s: &Store, out: &mut Vec<u8>) {
let tables = s.table_list();
arr(out, tables.len());
for t in &tables {
arr(out, 12);
bulk(out, b"name");
bulk(out, &t.name);
bulk(out, b"prefix");
bulk(out, &t.prefix);
bulk(out, b"pk");
bulk(out, &t.pk);
bulk(out, b"columns");
bulk(out, t.columns.len().to_string().as_bytes());
bulk(out, b"indexes");
bulk(out, t.indexes.len().to_string().as_bytes());
bulk(out, b"orderpaths");
bulk(out, t.orderpaths.len().to_string().as_bytes());
}
}
fn cmd_verify(s: &Store, name: &[u8], out: &mut Vec<u8>) {
const LABELS: [&[u8]; 6] =
[b"entries", b"bytes", b"coerce_failures", b"duplicates", b"drift", b"checked"];
let Ok((per_index, spot)) = s.table_verify(name) else {
let n = String::from_utf8_lossy(name);
return err(out, &format!("ERR no such table '{n}' (TABLE.LIST enumerates them)"));
};
arr(out, per_index.len() + 1);
for (iname, sums) in &per_index {
arr(out, 14);
bulk(out, b"index");
bulk(out, iname);
for (label, v) in LABELS.iter().zip(sums.iter()) {
bulk(out, label);
bulk(out, v.to_string().as_bytes());
}
}
arr(out, 4);
bulk(out, b"spotcheck_rows");
bulk(out, spot[0].to_string().as_bytes());
bulk(out, b"spotcheck_type_mismatches");
bulk(out, spot[1].to_string().as_bytes());
}