Fixes for stage2 compiler

This commit is contained in:
jaina heartles 2022-07-13 07:42:30 -07:00
parent cfebc3b0cc
commit d694674585
5 changed files with 92 additions and 44 deletions

View file

@ -1,5 +1,6 @@
const std = @import("std");
const util = @import("util");
const builtin = @import("builtin");
const http = @import("./lib.zig");
@ -26,7 +27,7 @@ pub fn Router(comptime ServerContext: type, comptime RequestContext: type) type
routes: []const Route,
pub const Handler = fn (ServerContext, RequestContext, RouteArgs) anyerror!void;
pub const Handler = *const fn (ServerContext, RequestContext, RouteArgs) anyerror!void;
pub const Route = struct {
pub const Args = RouteArgs;
@ -75,6 +76,10 @@ pub fn Router(comptime ServerContext: type, comptime RequestContext: type) type
if (req_segments.next() != null) return error.RouteNotApplicable;
std.log.debug("selected route {s} {s}", .{ @tagName(route.method), route.path });
if (builtin.zig_backend == .stage1) {
return route.handler.*(sctx, rctx, args);
}
return route.handler(sctx, rctx, args);
}
};

View file

@ -124,8 +124,31 @@ pub const ApiSource = struct {
pub const Conn = ApiConn(db.Database);
pub fn init(alloc: std.mem.Allocator, cfg: Config) !ApiSource {
var my_db = try db.Database.init();
{
const C = db.builder.Condition;
const qt = db.builder.queryTables(&.{ models.User, models.User, models.LocalUser, models.Invite });
const UInviter = qt[0];
const UInvitee = qt[1];
const LUInvitee = qt[2];
const Invite = qt[3];
const q = comptime db.builder.Query
.from(qt)
.select(&.{ UInviter.select(.username), UInvitee.select(.username), Invite.select(.id) })
.where(C.all(&.{
C.eql(UInviter.field(.id), Invite.field(.created_by)),
C.eql(LUInvitee.field(.invite_id), Invite.field(.id)),
C.eql(LUInvitee.field(.user_id), UInvitee.field(.id)),
}));
const result = (try my_db.execRowQuery(q, alloc)) orelse unreachable;
std.log.debug("{s} invited {s}", .{ result[0], result[1] });
}
return ApiSource{
.db = try db.Database.init(),
//.db = try db.Database.init(),
.db = my_db,
.internal_alloc = alloc,
.config = cfg,
};
@ -230,8 +253,13 @@ fn ApiConn(comptime DbConn: type) type {
return note;
}
pub fn getNote(self: *Self, id: Uuid) !?models.Note {
return self.db.getBy(models.Note, .id, id, self.arena.allocator());
//pub fn getNote(self: *Self, id: Uuid) !?models.Note {
pub fn getNote(self: *Self, id: Uuid) !?[]const u8 {
const row = try self.db.execRow("select content from note where id = ?", .{id}, &.{[]const u8}, self.arena.allocator());
if (row) |results| {
return results[0];
} else return null;
//return self.db.getBy(models.Note, .id, id, self.arena.allocator());
}
pub fn getActor(self: *Self, user_id: Uuid) !?models.Actor {
@ -325,8 +353,10 @@ fn ApiConn(comptime DbConn: type) type {
const hash = try PwHash.strHash(info.password, .{ .allocator = self.internal_alloc, .params = pw_hash_params, .encoding = pw_hash_encoding }, &buf);
const community_id = if (info.community_host) |host| blk: {
//const id_tuple = (try self.db.execRow("select id from community where host = '?'", host, &.{Uuid}, self.arena.allocator())) orelse return error.CommunityNotFound;
const community = (try self.db.getBy(models.Community, .host, host, self.arena.allocator())) orelse return error.CommunityNotFound;
break :blk community.id;
//break :blk id_tuple[0];
} else null;
const user = models.User{

View file

@ -9,24 +9,7 @@ const DateTime = util.DateTime;
const String = []const u8;
const comptimePrint = std.fmt.comptimePrint;
// Stuff in here introduces compile errors in seemingly unused parts of
// the stdlib. Maybe just broken on this version of zig?
const broken = struct {
fn baseTypeName(comptime T: type) []const u8 {
comptime {
const name = @typeName(T);
const start = for (name) |_, i| {
if (name[name.len - i] == '.') break name.len - i;
} else 0;
return name[start..];
}
}
fn tableNameBroken(comptime T: type) String {
return util.case.pascalToSnake(baseTypeName(T));
}
};
pub const builder = @import("./db/query_builder.zig");
fn tableName(comptime T: type) String {
return switch (T) {
@ -131,16 +114,6 @@ fn fieldsExcept(comptime T: type, comptime to_ignore: []const String) []const St
}
}
fn maxTagNameLen(comptime Enum: type) usize {
comptime {
var max_len: usize = 0;
for (std.meta.fieldNames(Enum)) |field| {
if (field.len > max_len) max_len = field.len;
}
return max_len;
}
}
// Binds a value to a parameter in the query. Use this instead of string
// concatenation to avoid injection attacks;
// If a given type is not supported by this function, you can add support by
@ -222,6 +195,46 @@ pub const Database = struct {
self.db.close();
}
pub fn execRowQuery(self: *Database, comptime q: builder.Query, alloc: std.mem.Allocator) !?q.rowType() {
std.log.debug("executing sql:\n===\n{s}\n===", .{q.str()});
var stmt = try self.db.prepare(q.str());
errdefer stmt.finalize();
const row = (try stmt.step()) orelse return null;
std.log.debug("successful query", .{});
var result: q.rowType() = undefined;
inline for (std.meta.fields(q.rowType())) |f, i| {
result[i] = try getAlloc(row, f.field_type, i, alloc);
}
return result;
}
// Lower level function
pub fn execRow(
self: *Database,
comptime q: []const u8,
args: anytype,
comptime return_types: []const type,
alloc: std.mem.Allocator,
) !?std.meta.Tuple(return_types) {
var stmt = try self.db.prepare(q);
errdefer stmt.finalize();
inline for (std.meta.fields(@TypeOf(args))) |field, i| {
try bind(stmt, @intCast(u15, i + 1), @field(args, field.name));
}
const row = (try stmt.step()) orelse return null;
var result: std.meta.Tuple(return_types) = undefined;
inline for (std.meta.fields(@TypeOf(result))) |field, i| {
@field(result, field.name) = try getAlloc(row, field.field_type, i, alloc);
}
return result;
}
// Returns the first row that satisfies an equality check on the
// field specified
pub fn getBy(

View file

@ -15,22 +15,22 @@ const router = Router{
.routes = &[_]Route{
Route.new(.GET, "/healthcheck", c.healthcheck),
Route.new(.POST, "/auth/register", c.auth.register),
Route.new(.POST, "/auth/login", c.auth.login),
Route.new(.POST, "/auth/register", &c.auth.register),
Route.new(.POST, "/auth/login", &c.auth.login),
Route.new(.POST, "/notes", c.notes.create),
Route.new(.GET, "/notes/:id", c.notes.get),
Route.new(.POST, "/notes", &c.notes.create),
Route.new(.GET, "/notes/:id", &c.notes.get),
Route.new(.GET, "/notes/:id/reacts", c.notes.reacts.list),
Route.new(.POST, "/notes/:id/reacts", c.notes.reacts.create),
Route.new(.GET, "/notes/:id/reacts", &c.notes.reacts.list),
Route.new(.POST, "/notes/:id/reacts", &c.notes.reacts.create),
Route.new(.GET, "/actors/:id", c.actors.get),
Route.new(.GET, "/actors/:id", &c.actors.get),
Route.new(.POST, "/admin/invites", c.admin.invites.create),
Route.new(.GET, "/admin/invites/:id", c.admin.invites.get),
Route.new(.POST, "/admin/invites", &c.admin.invites.create),
Route.new(.GET, "/admin/invites/:id", &c.admin.invites.get),
Route.new(.POST, "/admin/communities", c.admin.communities.create),
Route.new(.GET, "/admin/communities/:host", c.admin.communities.get),
Route.new(.POST, "/admin/communities", &c.admin.communities.create),
Route.new(.GET, "/admin/communities/:host", &c.admin.communities.get),
},
};

View file

@ -12,7 +12,7 @@ pub const Sqlite = struct {
pub fn open(path: [:0]const u8) !Sqlite {
var db: ?*c.sqlite3 = undefined;
const err = c.sqlite3_open_v2(path, &db, c.SQLITE_OPEN_READWRITE | c.SQLITE_OPEN_CREATE, null);
const err = c.sqlite3_open_v2(@ptrCast([*c]const u8, path), &db, c.SQLITE_OPEN_READWRITE | c.SQLITE_OPEN_CREATE, null);
if (err != c.SQLITE_OK) return error.UnknownError;
return Sqlite{