Fixes for stage2 compiler
This commit is contained in:
parent
cfebc3b0cc
commit
d694674585
5 changed files with 92 additions and 44 deletions
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
Loading…
Reference in a new issue