Add conditions to query builder

This commit is contained in:
jaina heartles 2022-08-03 21:32:59 -07:00
parent 4087345323
commit 80ded57904
1 changed files with 69 additions and 0 deletions

View File

@ -0,0 +1,69 @@
const std = @import("std");
const util = @import("util");
const String = []const u8;
const comptimePrint = std.fmt.comptimePrint;
// Combines an array/tuple of strings into a single string, with a copy of
// joiner in between each one
fn join(comptime vals: []const String, comptime joiner: String) String {
if (vals.len == 0) return "";
var result: String = "";
for (vals) |v| {
result = comptimePrint("{s}{s}{s}", .{ result, joiner, v });
}
return result[joiner.len..];
}
fn joinConditions(comptime cs: []const Condition, comptime joiner: String) String {
var strs: [cs.len]String = undefined;
for (cs) |v, i| strs[i] = v.str();
return join(&strs, joiner);
}
pub const Condition = union(enum) {
const BinaryOp = struct {
lhs: String,
rhs: String,
};
eql: BinaryOp,
is_null: String,
val: String,
not: *const Condition,
all: []const Condition,
any: []const Condition,
fn str(comptime self: Condition) String {
comptime {
return comptimePrint("({s})", .{switch (self) {
.eql => |op| comptimePrint("{s} = {s}", .{ op.lhs, op.rhs }),
.is_null => |val| comptimePrint("{s} IS NULL", .{val}),
.val => |val| val,
.not => |c| comptimePrint("NOT {s}", .{c.str()}),
.all => |cs| joinConditions(cs, " AND "),
.any => |cs| joinConditions(cs, " OR "),
}});
}
}
};
test "Condition.str()" {
try std.testing.expectEqualStrings(
"((abc = def) AND (def = abc))",
(comptime Condition{ .all = &.{
.{ .eql = .{ .lhs = "abc", .rhs = "def" } },
.{ .eql = .{ .lhs = "def", .rhs = "abc" } },
} }).str(),
);
try std.testing.expectEqualStrings(
"((abc IS NULL) OR (NOT (def)))",
(comptime Condition{ .any = &.{
.{ .is_null = "abc" },
.{ .not = &.{ .val = "def" } },
} }).str(),
);
}