fediglam/src/sql/lib.zig

99 lines
2.9 KiB
Zig

const std = @import("std");
const postgres = @import("./postgres.zig");
const sqlite = @import("./sqlite.zig");
const Allocator = std.mem.Allocator;
pub const Type = enum {
postgres,
sqlite,
};
pub const Config = union(Type) {
postgres: struct {
conn_str: [:0]const u8,
},
sqlite: struct {
file_path: [:0]const u8,
},
};
//pub const OpenError = sqlite.OpenError | postgres.OpenError;
// Represents a set of results.
// row() must be called until it returns null, or the query may not complete
// Must be deallocated by a call to finish()
pub const Results = union(Type) {
postgres: postgres.Results,
sqlite: sqlite.Results,
pub fn finish(self: Results) void {
switch (self) {
.postgres => |pg| pg.finish(),
.sqlite => |lite| lite.finish(),
}
}
// can be used as an optimization to reduce memory reallocation
// only works on postgres
pub fn rowCount(self: Results) ?usize {
return switch (self) {
.postgres => |pg| pg.rowCount(),
.sqlite => null, // not possible without repeating the query
};
}
pub fn row(self: *Results) !?Row {
return switch (self.*) {
.postgres => |*pg| if (try pg.row()) |r| Row{ .postgres = r } else null,
.sqlite => |*lite| if (try lite.row()) |r| Row{ .sqlite = r } else null,
};
}
};
// Row is invalidated by the next call to result.row()
pub const Row = union(Type) {
postgres: postgres.Row,
sqlite: sqlite.Row,
// Returns a value of type T from the zero-indexed column given by idx.
// Not all types require an allocator to be present. If an allocator is needed but
// not required, it will return error.AllocatorRequired.
// The caller is responsible for deallocating T, if relevant.
pub fn get(self: Row, comptime T: type, idx: u15, alloc: ?Allocator) !T {
return switch (self) {
.postgres => |pg| pg.get(T, idx, alloc),
.sqlite => |lite| lite.get(T, idx, alloc),
};
}
};
pub const Db = union(Type) {
postgres: postgres.Db,
sqlite: sqlite.Db,
pub fn open(cfg: Config) !Db {
return switch (cfg) {
.postgres => |postgres_cfg| Db{
.postgres = try postgres.Db.open(postgres_cfg.conn_str),
},
.sqlite => |lite_cfg| Db{
.sqlite = try sqlite.Db.open(lite_cfg.file_path),
},
};
}
pub fn close(self: Db) void {
switch (self) {
.postgres => |pg| pg.close(),
.sqlite => |lite| lite.close(),
}
}
pub fn exec(self: Db, sql: [:0]const u8, args: anytype, alloc: Allocator) !Results {
return switch (self) {
.postgres => |pg| Results{ .postgres = try pg.exec(sql, args, alloc) },
.sqlite => |lite| Results{ .sqlite = try lite.exec(sql, args) },
};
}
};