feat: add cmdTableSelect and cmdTableExplain to repl
This commit is contained in:
1 parent
73b247d29d
commit
6820cfca72
1 file changed
+143
+143
@@ -322,3 +322,146 @@ pub const Repl = struct {
|
||||
}
|
||||
}
|
||||
|
||||
/// `table select <table> [expr...] [--limit N] [--offset N] [--order-by
|
||||
/// field[:desc][,field[:desc]...]]`: interactive counterpart of the
|
||||
/// one-shot CLI's `table select` (main.zig's `runTable`) over
|
||||
/// query.zig's `Table.selectPageOrdered`, same expr grammar (expr.zig)
|
||||
/// and `--limit`/`--offset`/`--order-by` conventions.
|
||||
fn cmdTableSelect(self: *Repl, args: []const []const u8, writer: anytype) !void {
|
||||
if (args.len < 1) return ReplError.WrongArgCount;
|
||||
var table = try Table.open(self.db, self.allocator, args[0]);
|
||||
defer table.deinit();
|
||||
|
||||
const sel = try extractSelectFlags(self.allocator, args[1..]);
|
||||
defer self.allocator.free(sel.rest);
|
||||
defer self.allocator.free(sel.flags.orderBy);
|
||||
|
||||
const exprText = try std.mem.join(self.allocator, " ", sel.rest);
|
||||
defer self.allocator.free(exprText);
|
||||
|
||||
var parsed: ?exprmod.Parsed = null;
|
||||
defer if (parsed) |*p| p.deinit();
|
||||
if (exprText.len > 0) {
|
||||
parsed = try exprmod.parse(self.allocator, exprText);
|
||||
}
|
||||
const pred: ?querymod.Predicate = if (parsed) |p| p.predicate else null;
|
||||
|
||||
const rows = try table.selectPageOrdered(pred, .{ .offset = sel.flags.page.offset, .limit = sel.flags.page.limit }, sel.flags.orderBy);
|
||||
defer querymod.freeRows(self.allocator, rows);
|
||||
for (rows) |r| try printRow(writer, r);
|
||||
}
|
||||
|
||||
/// `table explain <table> [expr...]`: interactive counterpart of the
|
||||
/// one-shot CLI's `table explain` (main.zig's `runTable`), reporting
|
||||
/// which strategy `table select` would use for the same predicate
|
||||
/// without running it - `query.Table.explain` over the same expr
|
||||
/// grammar `cmdTableSelect` already uses.
|
||||
fn cmdTableExplain(self: *Repl, args: []const []const u8, writer: anytype) !void {
|
||||
if (args.len < 1) return ReplError.WrongArgCount;
|
||||
var table = try Table.open(self.db, self.allocator, args[0]);
|
||||
defer table.deinit();
|
||||
|
||||
const exprText = try std.mem.join(self.allocator, " ", args[1..]);
|
||||
defer self.allocator.free(exprText);
|
||||
|
||||
var parsed: ?exprmod.Parsed = null;
|
||||
defer if (parsed) |*p| p.deinit();
|
||||
if (exprText.len > 0) {
|
||||
parsed = try exprmod.parse(self.allocator, exprText);
|
||||
}
|
||||
const pred: ?querymod.Predicate = if (parsed) |p| p.predicate else null;
|
||||
|
||||
var plan = try table.explain(self.allocator, pred);
|
||||
defer plan.deinit(self.allocator);
|
||||
try printPlan(writer, plan);
|
||||
}
|
||||
|
||||
/// `table update <table> --set field=value[,field=value...] [expr...]`:
|
||||
/// interactive counterpart of the one-shot CLI's `table update`
|
||||
/// (main.zig's `runTable`) over `query.Table.updateWhere`, same
|
||||
/// `--set`/expr grammar. Prints the number of rows updated.
|
||||
fn cmdTableUpdate(self: *Repl, args: []const []const u8, writer: anytype) !void {
|
||||
if (args.len < 1) return ReplError.WrongArgCount;
|
||||
var table = try Table.open(self.db, self.allocator, args[0]);
|
||||
defer table.deinit();
|
||||
|
||||
const setf = try extractSetFlag(self.allocator, args[1..]);
|
||||
defer self.allocator.free(setf.sets);
|
||||
defer self.allocator.free(setf.rest);
|
||||
|
||||
const exprText = try std.mem.join(self.allocator, " ", setf.rest);
|
||||
defer self.allocator.free(exprText);
|
||||
|
||||
var parsed: ?exprmod.Parsed = null;
|
||||
defer if (parsed) |*p| p.deinit();
|
||||
if (exprText.len > 0) {
|
||||
parsed = try exprmod.parse(self.allocator, exprText);
|
||||
}
|
||||
const pred: ?querymod.Predicate = if (parsed) |p| p.predicate else null;
|
||||
|
||||
const updated = try table.updateWhere(pred, setf.sets);
|
||||
try writer.print("{d}\n", .{updated});
|
||||
}
|
||||
|
||||
/// `table delete <table> [expr...]`: interactive counterpart of the
|
||||
/// one-shot CLI's `table delete` (main.zig's `runTable`) over
|
||||
/// `query.Table.deleteWhere`, same expr grammar as `cmdTableSelect`/
|
||||
/// `cmdTableExplain` (empty expr deletes every row). Prints the number
|
||||
/// of rows deleted.
|
||||
fn cmdTableDelete(self: *Repl, args: []const []const u8, writer: anytype) !void {
|
||||
if (args.len < 1) return ReplError.WrongArgCount;
|
||||
var table = try Table.open(self.db, self.allocator, args[0]);
|
||||
defer table.deinit();
|
||||
|
||||
const exprText = try std.mem.join(self.allocator, " ", args[1..]);
|
||||
defer self.allocator.free(exprText);
|
||||
|
||||
var parsed: ?exprmod.Parsed = null;
|
||||
defer if (parsed) |*p| p.deinit();
|
||||
if (exprText.len > 0) {
|
||||
parsed = try exprmod.parse(self.allocator, exprText);
|
||||
}
|
||||
const pred: ?querymod.Predicate = if (parsed) |p| p.predicate else null;
|
||||
|
||||
const deleted = try table.deleteWhere(pred);
|
||||
try writer.print("{d}\n", .{deleted});
|
||||
}
|
||||
|
||||
/// `table join [--left|--right|--full] <leftTable> <leftField>
|
||||
/// <rightTable> <rightField> [--limit N] [--offset N]`: interactive
|
||||
/// counterpart of the one-shot CLI's `table join` over join.zig's four
|
||||
/// join functions. With no flag, prints inner-join pairs (`L <row>`
|
||||
/// then `R <row>`); `--left`/`--right`/`--full` print `L (nil)`/
|
||||
/// `R (nil)` for the unmatched side exactly like the CLI.
|
||||
/// `--limit`/`--offset` window the already-joined result through
|
||||
/// `join.applyPage`, same convention as `table select`'s paging (0 or
|
||||
/// omitted = unlimited). Predicates on either side are not exposed here
|
||||
/// (same deliberately minimal CLI surface as `table join` itself - the
|
||||
/// richer path is the `join.zig` library API, as its own tests cover).
|
||||
fn cmdTableJoin(self: *Repl, args: []const []const u8, writer: anytype) !void {
|
||||
const JoinMode = enum { inner, left, right, full };
|
||||
var mode: JoinMode = .inner;
|
||||
var positional = std.ArrayList([]const u8).init(self.allocator);
|
||||
defer positional.deinit();
|
||||
for (args) |a| {
|
||||
if (std.mem.eql(u8, a, "--left")) {
|
||||
mode = .left;
|
||||
} else if (std.mem.eql(u8, a, "--right")) {
|
||||
mode = .right;
|
||||
} else if (std.mem.eql(u8, a, "--full")) {
|
||||
mode = .full;
|
||||
} else {
|
||||
try positional.append(a);
|
||||
}
|
||||
}
|
||||
const pf = try extractPageFlags(self.allocator, positional.items);
|
||||
defer self.allocator.free(pf.rest);
|
||||
if (pf.rest.len != 4) return ReplError.WrongArgCount;
|
||||
const jargs = pf.rest;
|
||||
const page = querymod.Page{ .offset = pf.page.offset, .limit = pf.page.limit };
|
||||
|
||||
var left = try Table.open(self.db, self.allocator, jargs[0]);
|
||||
defer left.deinit();
|
||||
var right = try Table.open(self.db, self.allocator, jargs[2]);
|
||||
defer right.deinit();
|
||||
|
||||
Reference in new issue
Block a user