Remove storage policy from sql lib
This commit is contained in:
parent
ada0eb71f5
commit
3e91d66565
2 changed files with 90 additions and 88 deletions
|
@ -1,11 +1,47 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const sql = @import("sql");
|
const sql = @import("sql");
|
||||||
const models = @import("./models.zig");
|
const models = @import("./models.zig");
|
||||||
|
const util = @import("util");
|
||||||
|
|
||||||
const Uuid = @import("util").Uuid;
|
const Uuid = util.Uuid;
|
||||||
|
const DateTime = util.DateTime;
|
||||||
const String = []const u8;
|
const String = []const u8;
|
||||||
const comptimePrint = std.fmt.comptimePrint;
|
const comptimePrint = std.fmt.comptimePrint;
|
||||||
|
|
||||||
|
pub fn ByteArray(comptime n: usize) type {
|
||||||
|
return struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
data: [n]u8,
|
||||||
|
|
||||||
|
pub fn bindToSql(self: Self, stmt: sql.PreparedStmt, idx: u15) !void {
|
||||||
|
return stmt.bindBlob(idx, &self.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getFromSql(row: sql.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 bindToSql(self: Self, stmt: sql.PreparedStmt, idx: u15) !void {
|
||||||
|
return stmt.bindBlob(idx, self.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getFromSql(row: sql.Row, idx: u15, alloc: std.mem.Alloc) !void {
|
||||||
|
return Self{
|
||||||
|
.data = try row.getBlobAlloc(idx, alloc),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fn tableName(comptime T: type) String {
|
fn tableName(comptime T: type) String {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
models.Note => "note",
|
models.Note => "note",
|
||||||
|
@ -98,6 +134,38 @@ fn fieldsExcept(comptime T: type, comptime to_ignore: []const String) []const St
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bind(stmt: sql.PreparedStmt, idx: u15, val: anytype) !void {
|
||||||
|
return switch (@TypeOf(val)) {
|
||||||
|
[]u8, []const u8 => stmt.bindText(idx, val),
|
||||||
|
i64 => stmt.bindI64(idx, val),
|
||||||
|
Uuid => stmt.bindUuid(idx, val),
|
||||||
|
DateTime => stmt.bindDateTime(idx, val),
|
||||||
|
@TypeOf(null) => stmt.bindNull(idx),
|
||||||
|
else => |T| switch (@typeInfo(T)) {
|
||||||
|
.Optional => if (val) |v| bind(stmt, idx, v) else stmt.bindNull(idx),
|
||||||
|
.Struct, .Union, .Enum, .Opaque => if (@hasDecl(T, "bindToSql")) val.bindToSql(stmt, idx),
|
||||||
|
else => @compileError("Unknown Type" ++ @typeName(T)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getAlloc(row: sql.Row, comptime T: type, idx: u15, alloc: std.mem.Allocator) !T {
|
||||||
|
return switch (T) {
|
||||||
|
[]u8, []const u8 => row.getTextAlloc(idx, alloc),
|
||||||
|
i64 => row.getI64(idx),
|
||||||
|
Uuid => row.getUuid(idx),
|
||||||
|
DateTime => row.getDateTime(idx),
|
||||||
|
|
||||||
|
else => {
|
||||||
|
switch (@typeInfo(T)) {
|
||||||
|
.Optional => if (row.isNull(idx)) return null else return try getAlloc(row, std.meta.Child(T), idx, alloc),
|
||||||
|
.Struct, .Union, .Enum, .Opaque => if (@hasDecl(T, "getFromSql")) T.getFromSql(row, idx, alloc),
|
||||||
|
else => @compileError("unknown type " ++ @typeName(T)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub const Database = struct {
|
pub const Database = struct {
|
||||||
db: sql.Sqlite,
|
db: sql.Sqlite,
|
||||||
|
|
||||||
|
@ -194,14 +262,14 @@ pub const Database = struct {
|
||||||
var stmt = try self.db.prepare(q);
|
var stmt = try self.db.prepare(q);
|
||||||
defer stmt.finalize();
|
defer stmt.finalize();
|
||||||
|
|
||||||
try stmt.bind(1, val);
|
try bind(stmt, 1, val);
|
||||||
|
|
||||||
const row = (try stmt.step()) orelse return null;
|
const row = (try stmt.step()) orelse return null;
|
||||||
var result: T = undefined;
|
var result: T = undefined;
|
||||||
@field(result, field_name) = val;
|
@field(result, field_name) = val;
|
||||||
|
|
||||||
inline for (fields) |f, i| {
|
inline for (fields) |f, i| {
|
||||||
@field(result, f) = row.getAlloc(@TypeOf(@field(result, f)), i, alloc) catch unreachable;
|
@field(result, f) = getAlloc(row, @TypeOf(@field(result, f)), i, alloc) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -225,7 +293,7 @@ pub const Database = struct {
|
||||||
var stmt = try self.db.prepare(q);
|
var stmt = try self.db.prepare(q);
|
||||||
defer stmt.finalize();
|
defer stmt.finalize();
|
||||||
|
|
||||||
try stmt.bind(1, val);
|
try bind(stmt, 1, val);
|
||||||
|
|
||||||
var results = std.ArrayList(T).init(alloc);
|
var results = std.ArrayList(T).init(alloc);
|
||||||
|
|
||||||
|
@ -233,7 +301,7 @@ pub const Database = struct {
|
||||||
var item: T = undefined;
|
var item: T = undefined;
|
||||||
@field(item, field_name) = val;
|
@field(item, field_name) = val;
|
||||||
inline for (fields) |f, i| {
|
inline for (fields) |f, i| {
|
||||||
@field(item, f) = row.getAlloc(@TypeOf(@field(item, f)), i, alloc) catch unreachable;
|
@field(item, f) = getAlloc(row, @TypeOf(@field(item, f)), i, alloc) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
try results.append(item);
|
try results.append(item);
|
||||||
|
@ -258,7 +326,7 @@ pub const Database = struct {
|
||||||
var stmt = try self.db.prepare(q);
|
var stmt = try self.db.prepare(q);
|
||||||
defer stmt.finalize();
|
defer stmt.finalize();
|
||||||
|
|
||||||
try stmt.bind(1, val);
|
try bind(stmt, 1, val);
|
||||||
|
|
||||||
const row = (try stmt.step()) orelse unreachable;
|
const row = (try stmt.step()) orelse unreachable;
|
||||||
return @intCast(usize, try row.getI64(0));
|
return @intCast(usize, try row.getI64(0));
|
||||||
|
@ -282,7 +350,7 @@ pub const Database = struct {
|
||||||
var stmt = try self.db.prepare(q);
|
var stmt = try self.db.prepare(q);
|
||||||
defer stmt.finalize();
|
defer stmt.finalize();
|
||||||
|
|
||||||
try stmt.bind(1, val);
|
try bind(stmt, 1, val);
|
||||||
|
|
||||||
const row = (try stmt.step()) orelse unreachable;
|
const row = (try stmt.step()) orelse unreachable;
|
||||||
return (try row.getI64(0)) > 0;
|
return (try row.getI64(0)) > 0;
|
||||||
|
@ -300,7 +368,7 @@ pub const Database = struct {
|
||||||
defer stmt.finalize();
|
defer stmt.finalize();
|
||||||
|
|
||||||
inline for (fields) |f, i| {
|
inline for (fields) |f, i| {
|
||||||
try stmt.bind(i + 1, @field(val, f));
|
try bind(stmt, i + 1, @field(val, f));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((try stmt.step()) != null) return error.UnknownError;
|
if ((try stmt.step()) != null) return error.UnknownError;
|
||||||
|
|
|
@ -7,40 +7,6 @@ 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,
|
||||||
|
|
||||||
|
@ -75,6 +41,10 @@ pub const Row = struct {
|
||||||
stmt: *c.sqlite3_stmt,
|
stmt: *c.sqlite3_stmt,
|
||||||
db: *c.sqlite3,
|
db: *c.sqlite3,
|
||||||
|
|
||||||
|
pub fn isNull(self: Row, idx: u15) bool {
|
||||||
|
return c.sqlite3_column_type(self.stmt, idx) == c.SQLITE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getI64(self: Row, idx: u15) !i64 {
|
pub fn getI64(self: Row, idx: u15) !i64 {
|
||||||
return @intCast(i64, c.sqlite3_column_int64(self.stmt, idx));
|
return @intCast(i64, c.sqlite3_column_int64(self.stmt, idx));
|
||||||
}
|
}
|
||||||
|
@ -124,86 +94,50 @@ pub const Row = struct {
|
||||||
pub fn getDateTime(self: Row, idx: u15) !DateTime {
|
pub fn getDateTime(self: Row, idx: u15) !DateTime {
|
||||||
return DateTime{ .seconds_since_epoch = try self.getI64(idx) };
|
return DateTime{ .seconds_since_epoch = try self.getI64(idx) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getAlloc(self: Row, comptime T: type, idx: u15, alloc: std.mem.Allocator) !T {
|
|
||||||
// TODO: handle optionals
|
|
||||||
return switch (T) {
|
|
||||||
[]u8, []const u8 => self.getTextAlloc(idx, alloc),
|
|
||||||
i64 => self.getI64(idx),
|
|
||||||
Uuid => self.getUuid(idx),
|
|
||||||
DateTime => self.getDateTime(idx),
|
|
||||||
|
|
||||||
else => {
|
|
||||||
switch (@typeInfo(T)) {
|
|
||||||
.Optional => switch (c.sqlite3_column_type(self.stmt, idx)) {
|
|
||||||
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)),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PreparedStmt = struct {
|
pub const PreparedStmt = struct {
|
||||||
stmt: *c.sqlite3_stmt,
|
stmt: *c.sqlite3_stmt,
|
||||||
db: *c.sqlite3,
|
db: *c.sqlite3,
|
||||||
|
|
||||||
pub fn bindNull(self: *PreparedStmt, idx: u15) !void {
|
pub fn bindNull(self: PreparedStmt, idx: u15) !void {
|
||||||
return switch (c.sqlite3_bind_null(self.stmt, idx)) {
|
return switch (c.sqlite3_bind_null(self.stmt, idx)) {
|
||||||
c.SQLITE_OK => {},
|
c.SQLITE_OK => {},
|
||||||
else => error.UnknownError,
|
else => error.UnknownError,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bindUuid(self: *PreparedStmt, idx: u15, id: Uuid) !void {
|
pub fn bindUuid(self: PreparedStmt, idx: u15, id: Uuid) !void {
|
||||||
const str = id.toCharArray();
|
const str = id.toCharArray();
|
||||||
return self.bindText(idx, &str);
|
return self.bindText(idx, &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bindText(self: *PreparedStmt, idx: u15, str: []const u8) !void {
|
pub fn bindText(self: PreparedStmt, idx: u15, str: []const u8) !void {
|
||||||
return switch (c.sqlite3_bind_text(self.stmt, idx, str.ptr, @intCast(c_int, str.len), c.SQLITE_TRANSIENT)) {
|
return switch (c.sqlite3_bind_text(self.stmt, idx, str.ptr, @intCast(c_int, str.len), c.SQLITE_TRANSIENT)) {
|
||||||
c.SQLITE_OK => {},
|
c.SQLITE_OK => {},
|
||||||
else => error.UnknownError,
|
else => error.UnknownError,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bindBlob(self: *PreparedStmt, idx: u15, blob: []const u8) !void {
|
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)) {
|
return switch (c.sqlite3_bind_blob64(self.stmt, idx, blob.ptr, blob.len, c.SQLITE_TRANSIENT)) {
|
||||||
c.SQLITE_OK => {},
|
c.SQLITE_OK => {},
|
||||||
else => error.UnknownError,
|
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 => {},
|
||||||
else => error.UnknownError,
|
else => error.UnknownError,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bindDateTime(self: *PreparedStmt, idx: u15, val: DateTime) !void {
|
pub fn bindDateTime(self: PreparedStmt, idx: u15, val: DateTime) !void {
|
||||||
return self.bindI64(idx, val.seconds_since_epoch);
|
return self.bindI64(idx, val.seconds_since_epoch);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(self: *PreparedStmt, idx: u15, val: anytype) !void {
|
pub fn step(self: PreparedStmt) !?Row {
|
||||||
return switch (@TypeOf(val)) {
|
|
||||||
[]u8, []const u8 => self.bindText(idx, val),
|
|
||||||
i64 => self.bindI64(idx, val),
|
|
||||||
Uuid => self.bindUuid(idx, val),
|
|
||||||
DateTime => self.bindDateTime(idx, val),
|
|
||||||
@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)),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn step(self: *PreparedStmt) !?Row {
|
|
||||||
return switch (c.sqlite3_step(self.stmt)) {
|
return switch (c.sqlite3_step(self.stmt)) {
|
||||||
c.SQLITE_ROW => Row{ .stmt = self.stmt, .db = self.db },
|
c.SQLITE_ROW => Row{ .stmt = self.stmt, .db = self.db },
|
||||||
c.SQLITE_DONE => null,
|
c.SQLITE_DONE => null,
|
||||||
|
@ -216,15 +150,15 @@ pub const PreparedStmt = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finalize(self: *PreparedStmt) void {
|
pub fn finalize(self: PreparedStmt) void {
|
||||||
_ = c.sqlite3_finalize(self.stmt);
|
_ = c.sqlite3_finalize(self.stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(self: *PreparedStmt) void {
|
pub fn reset(self: PreparedStmt) void {
|
||||||
_ = c.sqlite3_reset(self.stmt);
|
_ = c.sqlite3_reset(self.stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getGeneratingSql(self: *PreparedStmt) ?[*:0]const u8 {
|
fn getGeneratingSql(self: PreparedStmt) ?[*:0]const u8 {
|
||||||
return c.sqlite3_sql(self.stmt);
|
return c.sqlite3_sql(self.stmt);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue