Use sql api for users

This commit is contained in:
jaina heartles 2022-07-16 11:41:09 -07:00
parent 40e7037444
commit 74fb8d2574
5 changed files with 49 additions and 33 deletions

View file

@ -47,7 +47,7 @@ pub const ApiServer = struct {
pub fn init(alloc: std.mem.Allocator) !ApiServer { pub fn init(alloc: std.mem.Allocator) !ApiServer {
return ApiServer{ return ApiServer{
.memdb = try memdb.Database.init(alloc), .memdb = try memdb.Database.init(alloc),
.prng = std.rand.DefaultPrng.init(1998), .prng = std.rand.DefaultPrng.init(@bitCast(u64, std.time.milliTimestamp())),
.db = try db.Database.init(), .db = try db.Database.init(),
}; };
@ -63,36 +63,34 @@ pub const ApiServer = struct {
// TODO: check for dupes // TODO: check for dupes
const note = reify(models.Note, id, info); const note = reify(models.Note, id, info);
try self.db.insertNote(note); try self.db.insert(models.Note, note);
//try self.memdb.notes.put(note);
return note; return note;
} }
pub fn createUser(self: *ApiServer, info: CreateInfo(models.User)) !models.User { pub fn createUser(self: *ApiServer, info: CreateInfo(models.User)) !models.User {
try self.memdb.users.lock();
defer self.memdb.users.unlock();
// TODO; real queries
const id = Uuid.randV4(self.prng.random()); const id = Uuid.randV4(self.prng.random());
// check for handle dupes // check for handle dupes
var iter = self.memdb.users.data.iterator(); //var iter = self.memdb.users.data.iterator();
while (iter.next()) |it| { //while (iter.next()) |it| {
if (std.mem.eql(u8, it.value_ptr.handle, info.handle)) { //if (std.mem.eql(u8, it.value_ptr.handle, info.handle)) {
return error.DuplicateHandle; //return error.DuplicateHandle;
} //}
} //}
// TODO: check for id dupes // TODO: check for id dupes
const user = reify(models.User, id, info); const user = reify(models.User, id, info);
try self.memdb.users.put(user); try self.db.insert(models.User, user);
return user; return user;
} }
pub fn getNote(self: *ApiServer, id: Uuid, alloc: std.mem.Allocator) !?models.Note { pub fn getNote(self: *ApiServer, id: Uuid, alloc: std.mem.Allocator) !?models.Note {
return self.db.getNoteById(id, alloc); return self.db.getById(models.Note, id, alloc);
//return self.memdb.notes.get(id, alloc); }
pub fn getUser(self: *ApiServer, id: Uuid, alloc: std.mem.Allocator) !?models.User {
return self.db.getById(models.User, id, alloc);
} }
}; };

View file

@ -79,6 +79,15 @@ pub fn getNote(srv: *RequestServer, ctx: *http.server.Context, args: RouteArgs)
try utils.respondJson(ctx, .ok, note, srv.alloc); try utils.respondJson(ctx, .ok, note, srv.alloc);
} }
pub fn getUser(srv: *RequestServer, ctx: *http.server.Context, args: RouteArgs) !void {
const id_str = args.get("id") orelse return error.NotFound;
const id = Uuid.parse(id_str) catch return utils.respondJson(ctx, .bad_request, .{ .@"error" = "Invalid UUID" }, srv.alloc);
const user = (try srv.api.getUser(id, srv.alloc)) orelse return utils.respondJson(ctx, .not_found, .{ .@"error" = "Note not found" }, srv.alloc);
defer api.free(srv.alloc, user);
try utils.respondJson(ctx, .ok, user, srv.alloc);
}
pub fn healthcheck(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void { pub fn healthcheck(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void {
try utils.respondJson(ctx, .ok, .{ .status = "ok" }, srv.alloc); try utils.respondJson(ctx, .ok, .{ .status = "ok" }, srv.alloc);
} }

View file

@ -91,27 +91,30 @@ fn fieldsExcept(comptime T: type, comptime to_ignore: []const String) []const St
pub const Database = struct { pub const Database = struct {
db: sql.Sqlite, db: sql.Sqlite,
pub fn init() !Database { const init_sql_stmts = [_][]const u8{
var db = try sql.Sqlite.open("./test.db");
errdefer db.close();
var stmt = try db.prepare(
\\CREATE TABLE IF NOT EXISTS \\CREATE TABLE IF NOT EXISTS
\\note( \\note(
\\ id TEXT PRIMARY KEY, \\ id TEXT PRIMARY KEY,
\\ content TEXT NOT NULL \\ content TEXT NOT NULL
\\) STRICT; \\) STRICT;
\\ ,
\\CREATE TABLE IF NOT EXISTS \\CREATE TABLE IF NOT EXISTS
\\user( \\user(
\\ id TEXT PRIMARY KEY, \\ id TEXT PRIMARY KEY,
\\ handle TEXT NOT NULL \\ handle TEXT NOT NULL
\\) STRICT; \\) STRICT;
\\ };
);
pub fn init() !Database {
var db = try sql.Sqlite.open("./test.db");
errdefer db.close();
for (init_sql_stmts) |stmt_sql| {
var stmt = try db.prepare(stmt_sql);
defer stmt.finalize(); defer stmt.finalize();
while (try stmt.step()) |_| {} while (try stmt.step()) |_| {}
}
return Database{ .db = db }; return Database{ .db = db };
} }

View file

@ -15,8 +15,10 @@ const RouteArgs = http.RouteArgs;
const router = Router{ const router = Router{
.routes = &[_]Route{ .routes = &[_]Route{
Route.new(.GET, "/healthcheck", c.healthcheck), Route.new(.GET, "/healthcheck", c.healthcheck),
Route.new(.GET, "/notes/:id", c.getNote), Route.new(.GET, "/notes/:id", c.getNote),
Route.new(.POST, "/notes", c.createNote), Route.new(.POST, "/notes", c.createNote),
Route.new(.GET, "/users/:id", c.getUser),
Route.new(.POST, "/users", c.createUser), Route.new(.POST, "/users", c.createUser),
}, },
}; };

View file

@ -23,7 +23,11 @@ pub const Sqlite = struct {
pub fn prepare(self: *Sqlite, sql: []const u8) !PreparedStmt { pub fn prepare(self: *Sqlite, sql: []const u8) !PreparedStmt {
var stmt: ?*c.sqlite3_stmt = undefined; var stmt: ?*c.sqlite3_stmt = undefined;
const err = c.sqlite3_prepare_v2(self.db, sql.ptr, @intCast(c_int, sql.len), &stmt, null); const err = c.sqlite3_prepare_v2(self.db, sql.ptr, @intCast(c_int, sql.len), &stmt, null);
if (err != c.SQLITE_OK) return error.UnknownError; if (err != c.SQLITE_OK) {
std.debug.print("sql error {}\n", .{err});
std.debug.print("{s}\n", .{c.sqlite3_errmsg(self.db)});
return error.UnknownError;
}
return PreparedStmt{ .stmt = stmt.?, .db = self.db }; return PreparedStmt{ .stmt = stmt.?, .db = self.db };
} }