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 std = @import("std");
|
||||||
const util = @import("util");
|
const util = @import("util");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
const http = @import("./lib.zig");
|
const http = @import("./lib.zig");
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ pub fn Router(comptime ServerContext: type, comptime RequestContext: type) type
|
||||||
|
|
||||||
routes: []const Route,
|
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 Route = struct {
|
||||||
pub const Args = RouteArgs;
|
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;
|
if (req_segments.next() != null) return error.RouteNotApplicable;
|
||||||
|
|
||||||
std.log.debug("selected route {s} {s}", .{ @tagName(route.method), route.path });
|
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);
|
return route.handler(sctx, rctx, args);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -124,8 +124,31 @@ pub const ApiSource = struct {
|
||||||
pub const Conn = ApiConn(db.Database);
|
pub const Conn = ApiConn(db.Database);
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator, cfg: Config) !ApiSource {
|
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{
|
return ApiSource{
|
||||||
.db = try db.Database.init(),
|
//.db = try db.Database.init(),
|
||||||
|
.db = my_db,
|
||||||
.internal_alloc = alloc,
|
.internal_alloc = alloc,
|
||||||
.config = cfg,
|
.config = cfg,
|
||||||
};
|
};
|
||||||
|
@ -230,8 +253,13 @@ fn ApiConn(comptime DbConn: type) type {
|
||||||
return note;
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getNote(self: *Self, id: Uuid) !?models.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) !?[]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 {
|
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 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 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;
|
const community = (try self.db.getBy(models.Community, .host, host, self.arena.allocator())) orelse return error.CommunityNotFound;
|
||||||
break :blk community.id;
|
break :blk community.id;
|
||||||
|
//break :blk id_tuple[0];
|
||||||
} else null;
|
} else null;
|
||||||
|
|
||||||
const user = models.User{
|
const user = models.User{
|
||||||
|
|
|
@ -9,24 +9,7 @@ const DateTime = util.DateTime;
|
||||||
const String = []const u8;
|
const String = []const u8;
|
||||||
const comptimePrint = std.fmt.comptimePrint;
|
const comptimePrint = std.fmt.comptimePrint;
|
||||||
|
|
||||||
// Stuff in here introduces compile errors in seemingly unused parts of
|
pub const builder = @import("./db/query_builder.zig");
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fn tableName(comptime T: type) String {
|
fn tableName(comptime T: type) String {
|
||||||
return switch (T) {
|
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
|
// Binds a value to a parameter in the query. Use this instead of string
|
||||||
// concatenation to avoid injection attacks;
|
// concatenation to avoid injection attacks;
|
||||||
// If a given type is not supported by this function, you can add support by
|
// 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();
|
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
|
// Returns the first row that satisfies an equality check on the
|
||||||
// field specified
|
// field specified
|
||||||
pub fn getBy(
|
pub fn getBy(
|
||||||
|
|
|
@ -15,22 +15,22 @@ const router = Router{
|
||||||
.routes = &[_]Route{
|
.routes = &[_]Route{
|
||||||
Route.new(.GET, "/healthcheck", c.healthcheck),
|
Route.new(.GET, "/healthcheck", c.healthcheck),
|
||||||
|
|
||||||
Route.new(.POST, "/auth/register", c.auth.register),
|
Route.new(.POST, "/auth/register", &c.auth.register),
|
||||||
Route.new(.POST, "/auth/login", c.auth.login),
|
Route.new(.POST, "/auth/login", &c.auth.login),
|
||||||
|
|
||||||
Route.new(.POST, "/notes", c.notes.create),
|
Route.new(.POST, "/notes", &c.notes.create),
|
||||||
Route.new(.GET, "/notes/:id", c.notes.get),
|
Route.new(.GET, "/notes/:id", &c.notes.get),
|
||||||
|
|
||||||
Route.new(.GET, "/notes/:id/reacts", c.notes.reacts.list),
|
Route.new(.GET, "/notes/:id/reacts", &c.notes.reacts.list),
|
||||||
Route.new(.POST, "/notes/:id/reacts", c.notes.reacts.create),
|
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(.POST, "/admin/invites", &c.admin.invites.create),
|
||||||
Route.new(.GET, "/admin/invites/:id", c.admin.invites.get),
|
Route.new(.GET, "/admin/invites/:id", &c.admin.invites.get),
|
||||||
|
|
||||||
Route.new(.POST, "/admin/communities", c.admin.communities.create),
|
Route.new(.POST, "/admin/communities", &c.admin.communities.create),
|
||||||
Route.new(.GET, "/admin/communities/:host", c.admin.communities.get),
|
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 {
|
pub fn open(path: [:0]const u8) !Sqlite {
|
||||||
var db: ?*c.sqlite3 = undefined;
|
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;
|
if (err != c.SQLITE_OK) return error.UnknownError;
|
||||||
|
|
||||||
return Sqlite{
|
return Sqlite{
|
||||||
|
|
Loading…
Reference in a new issue