Add sql support for blobs
This commit is contained in:
parent
fb5a7f9f30
commit
ada0eb71f5
1 changed files with 61 additions and 0 deletions
|
@ -7,6 +7,40 @@ const c = @cImport({
|
|||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
||||
pub fn ByteArray(comptime n: usize) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
data: [n]u8,
|
||||
|
||||
pub fn bindToSqlite(self: Self, stmt: *PreparedStmt, idx: u15) !void {
|
||||
return stmt.bindBlob(idx, &self.data);
|
||||
}
|
||||
|
||||
pub fn getFromSqlite(row: *Row, idx: u15, _: std.mem.Alloc) !Self {
|
||||
var self: Self = undefined;
|
||||
_ = try row.getBlob(idx, &self.data);
|
||||
return self;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub const ByteSlice = struct {
|
||||
const Self = @This();
|
||||
|
||||
data: []const u8,
|
||||
|
||||
pub fn bindToSqlite(self: Self, stmt: *PreparedStmt, idx: u15) !void {
|
||||
return stmt.bindBlob(idx, self.data);
|
||||
}
|
||||
|
||||
pub fn getFromSqlite(row: *Row, idx: u15, alloc: std.mem.Alloc) !void {
|
||||
return Self{
|
||||
.data = try row.getBlobAlloc(idx, alloc),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Sqlite = struct {
|
||||
db: *c.sqlite3,
|
||||
|
||||
|
@ -63,6 +97,24 @@ pub const Row = struct {
|
|||
return self.getText(idx, buf);
|
||||
}
|
||||
|
||||
pub fn getBlob(self: Row, idx: u15, buf: []u8) ![]u8 {
|
||||
const ptr = c.sqlite3_column_blob(self.stmt, idx);
|
||||
|
||||
const size = @intCast(usize, c.sqlite3_column_bytes(self.stmt, idx));
|
||||
if (size > buf.len) return error.StreamTooLong;
|
||||
for (ptr[0..size]) |ch, i| buf[i] = ch;
|
||||
|
||||
return buf[0..size];
|
||||
}
|
||||
|
||||
pub fn getBlobAlloc(self: Row, idx: u15, alloc: std.mem.Allocator) ![]u8 {
|
||||
const size = c.sqlite3_column_bytes(self.stmt, idx);
|
||||
var buf = try alloc.alloc(u8, @intCast(usize, size));
|
||||
errdefer alloc.free(buf);
|
||||
|
||||
return self.getBlob(idx, buf);
|
||||
}
|
||||
|
||||
pub fn getUuid(self: Row, idx: u15) !Uuid {
|
||||
var buf: [Uuid.string_len + 1]u8 = undefined;
|
||||
_ = try self.getText(idx, &buf);
|
||||
|
@ -87,6 +139,7 @@ pub const Row = struct {
|
|||
c.SQLITE_NULL => return null,
|
||||
else => return try self.getAlloc(std.meta.Child(T), idx, alloc),
|
||||
},
|
||||
.Struct, .Union, .Enum, .Opaque => if (@hasDecl(T, "getFromSqlite")) T.getFromSqlite(self, idx, alloc),
|
||||
else => @compileError("unknown type " ++ @typeName(T)),
|
||||
}
|
||||
},
|
||||
|
@ -117,6 +170,13 @@ pub const PreparedStmt = struct {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn bindBlob(self: *PreparedStmt, idx: u15, blob: []const u8) !void {
|
||||
return switch (c.sqlite3_bind_blob64(self.stmt, idx, blob.ptr, blob.len, c.SQLITE_TRANSIENT)) {
|
||||
c.SQLITE_OK => {},
|
||||
else => error.UnknownError,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn bindI64(self: *PreparedStmt, idx: u15, val: i64) !void {
|
||||
return switch (c.sqlite3_bind_int64(self.stmt, idx, val)) {
|
||||
c.SQLITE_OK => {},
|
||||
|
@ -137,6 +197,7 @@ pub const PreparedStmt = struct {
|
|||
@TypeOf(null) => self.bindNull(idx),
|
||||
else => |T| switch (@typeInfo(T)) {
|
||||
.Optional => if (val) |v| self.bind(idx, v) else self.bindNull(idx),
|
||||
.Struct, .Union, .Enum, .Opaque => if (@hasDecl(T, "bindToSqlite")) val.bindToSqlite(self, idx),
|
||||
else => @compileError("Unknown Type" ++ @typeName(T)),
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue