Add conditions to query builder
This commit is contained in:
parent
4087345323
commit
80ded57904
1 changed files with 69 additions and 0 deletions
69
src/main/db/query_builder.zig
Normal file
69
src/main/db/query_builder.zig
Normal 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(),
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue