prefect server in zig
at main 181 lines 6.2 kB view raw
1const std = @import("std"); 2const Allocator = std.mem.Allocator; 3 4const backend = @import("backend.zig"); 5const log = @import("../logging.zig"); 6 7pub const BlockDocumentRow = struct { 8 id: []const u8, 9 created: []const u8, 10 updated: []const u8, 11 name: ?[]const u8, 12 data: []const u8, 13 is_anonymous: bool, 14 block_type_id: []const u8, 15 block_type_name: ?[]const u8, 16 block_schema_id: []const u8, 17}; 18 19pub fn insert( 20 id: []const u8, 21 name: ?[]const u8, 22 data: []const u8, 23 is_anonymous: bool, 24 block_type_id: []const u8, 25 block_type_name: ?[]const u8, 26 block_schema_id: []const u8, 27) !void { 28 backend.db.exec( 29 \\INSERT INTO block_document (id, name, data, is_anonymous, block_type_id, block_type_name, block_schema_id) 30 \\VALUES (?, ?, ?, ?, ?, ?, ?) 31 , .{ 32 id, 33 name, 34 data, 35 @as(i32, if (is_anonymous) 1 else 0), 36 block_type_id, 37 block_type_name, 38 block_schema_id, 39 }) catch |err| { 40 log.err("database", "insert block_document error: {}", .{err}); 41 return err; 42 }; 43} 44 45pub fn getById(alloc: Allocator, id: []const u8) !?BlockDocumentRow { 46 var rows = backend.db.query( 47 \\SELECT id, created, updated, name, data, is_anonymous, 48 \\ block_type_id, block_type_name, block_schema_id 49 \\FROM block_document WHERE id = ? 50 , .{id}) catch return null; 51 defer rows.deinit(); 52 53 if (rows.next()) |row| { 54 return rowToBlockDocument(alloc, row); 55 } 56 return null; 57} 58 59pub fn getByTypeSlugAndName( 60 alloc: Allocator, 61 block_type_slug: []const u8, 62 name: []const u8, 63) !?BlockDocumentRow { 64 var rows = backend.db.query( 65 \\SELECT bd.id, bd.created, bd.updated, bd.name, bd.data, bd.is_anonymous, 66 \\ bd.block_type_id, bd.block_type_name, bd.block_schema_id 67 \\FROM block_document bd 68 \\JOIN block_type bt ON bd.block_type_id = bt.id 69 \\WHERE bt.slug = ? AND bd.name = ? 70 , .{ block_type_slug, name }) catch return null; 71 defer rows.deinit(); 72 73 if (rows.next()) |row| { 74 return rowToBlockDocument(alloc, row); 75 } 76 return null; 77} 78 79/// SQL for update - dialect-specific for datetime function 80const update_sql = struct { 81 const sqlite_with_schema = "UPDATE block_document SET data = ?, block_schema_id = ?, updated = datetime('now') WHERE id = ?"; 82 const sqlite_no_schema = "UPDATE block_document SET data = ?, updated = datetime('now') WHERE id = ?"; 83 const postgres_with_schema = "UPDATE block_document SET data = ?, block_schema_id = ?, updated = NOW()::TEXT WHERE id = ?"; 84 const postgres_no_schema = "UPDATE block_document SET data = ?, updated = NOW()::TEXT WHERE id = ?"; 85}; 86 87pub fn update( 88 id: []const u8, 89 data: []const u8, 90 block_schema_id: ?[]const u8, 91) !void { 92 if (block_schema_id) |schema_id| { 93 const sql = switch (backend.db.dialect) { 94 .sqlite => update_sql.sqlite_with_schema, 95 .postgres => update_sql.postgres_with_schema, 96 }; 97 backend.db.exec(sql, .{ data, schema_id, id }) catch |err| { 98 log.err("database", "update block_document error: {}", .{err}); 99 return err; 100 }; 101 } else { 102 const sql = switch (backend.db.dialect) { 103 .sqlite => update_sql.sqlite_no_schema, 104 .postgres => update_sql.postgres_no_schema, 105 }; 106 backend.db.exec(sql, .{ data, id }) catch |err| { 107 log.err("database", "update block_document error: {}", .{err}); 108 return err; 109 }; 110 } 111} 112 113pub fn list(alloc: Allocator, limit: usize) ![]BlockDocumentRow { 114 var results = std.ArrayListUnmanaged(BlockDocumentRow){}; 115 errdefer results.deinit(alloc); 116 117 var rows = backend.db.query( 118 \\SELECT id, created, updated, name, data, is_anonymous, 119 \\ block_type_id, block_type_name, block_schema_id 120 \\FROM block_document ORDER BY created DESC LIMIT ? 121 , .{@as(i64, @intCast(limit))}) catch |err| { 122 log.err("database", "list block_documents error: {}", .{err}); 123 return err; 124 }; 125 defer rows.deinit(); 126 127 while (rows.next()) |row| { 128 try results.append(alloc, rowToBlockDocument(alloc, row)); 129 } 130 131 return results.toOwnedSlice(alloc); 132} 133 134pub fn delete(id: []const u8) !bool { 135 const affected = backend.db.execWithRowCount( 136 "DELETE FROM block_document WHERE id = ?", 137 .{id}, 138 ) catch |err| { 139 log.err("database", "delete block_document error: {}", .{err}); 140 return err; 141 }; 142 return affected > 0; 143} 144 145pub fn listByTypeSlug(alloc: Allocator, block_type_slug: []const u8, limit: usize) ![]BlockDocumentRow { 146 var results = std.ArrayListUnmanaged(BlockDocumentRow){}; 147 errdefer results.deinit(alloc); 148 149 var rows = backend.db.query( 150 \\SELECT bd.id, bd.created, bd.updated, bd.name, bd.data, bd.is_anonymous, 151 \\ bd.block_type_id, bd.block_type_name, bd.block_schema_id 152 \\FROM block_document bd 153 \\JOIN block_type bt ON bd.block_type_id = bt.id 154 \\WHERE bt.slug = ? 155 \\ORDER BY bd.created DESC LIMIT ? 156 , .{ block_type_slug, @as(i64, @intCast(limit)) }) catch |err| { 157 log.err("database", "list block_documents by type error: {}", .{err}); 158 return err; 159 }; 160 defer rows.deinit(); 161 162 while (rows.next()) |row| { 163 try results.append(alloc, rowToBlockDocument(alloc, row)); 164 } 165 166 return results.toOwnedSlice(alloc); 167} 168 169fn rowToBlockDocument(alloc: Allocator, row: anytype) BlockDocumentRow { 170 return .{ 171 .id = alloc.dupe(u8, row.text(0)) catch "", 172 .created = alloc.dupe(u8, row.text(1)) catch "", 173 .updated = alloc.dupe(u8, row.text(2)) catch "", 174 .name = if (row.text(3).len > 0) alloc.dupe(u8, row.text(3)) catch null else null, 175 .data = alloc.dupe(u8, row.text(4)) catch "{}", 176 .is_anonymous = row.int(5) != 0, 177 .block_type_id = alloc.dupe(u8, row.text(6)) catch "", 178 .block_type_name = if (row.text(7).len > 0) alloc.dupe(u8, row.text(7)) catch null else null, 179 .block_schema_id = alloc.dupe(u8, row.text(8)) catch "", 180 }; 181}