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 Uuid = util.Uuid;
|
||||||
const DateTime = util.DateTime;
|
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 {
|
pub const Sqlite = struct {
|
||||||
db: *c.sqlite3,
|
db: *c.sqlite3,
|
||||||
|
|
||||||
|
@ -63,6 +97,24 @@ pub const Row = struct {
|
||||||
return self.getText(idx, buf);
|
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 {
|
pub fn getUuid(self: Row, idx: u15) !Uuid {
|
||||||
var buf: [Uuid.string_len + 1]u8 = undefined;
|
var buf: [Uuid.string_len + 1]u8 = undefined;
|
||||||
_ = try self.getText(idx, &buf);
|
_ = try self.getText(idx, &buf);
|
||||||
|
@ -87,6 +139,7 @@ pub const Row = struct {
|
||||||
c.SQLITE_NULL => return null,
|
c.SQLITE_NULL => return null,
|
||||||
else => return try self.getAlloc(std.meta.Child(T), idx, alloc),
|
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)),
|
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 {
|
pub fn bindI64(self: *PreparedStmt, idx: u15, val: i64) !void {
|
||||||
return switch (c.sqlite3_bind_int64(self.stmt, idx, val)) {
|
return switch (c.sqlite3_bind_int64(self.stmt, idx, val)) {
|
||||||
c.SQLITE_OK => {},
|
c.SQLITE_OK => {},
|
||||||
|
@ -137,6 +197,7 @@ pub const PreparedStmt = struct {
|
||||||
@TypeOf(null) => self.bindNull(idx),
|
@TypeOf(null) => self.bindNull(idx),
|
||||||
else => |T| switch (@typeInfo(T)) {
|
else => |T| switch (@typeInfo(T)) {
|
||||||
.Optional => if (val) |v| self.bind(idx, v) else self.bindNull(idx),
|
.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)),
|
else => @compileError("Unknown Type" ++ @typeName(T)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue