Delete unused deps, implement tkrzw and num encode

This commit is contained in:
Dendy 2022-10-31 01:21:34 +01:00
parent 9d9f297ac8
commit 895fc2b359
7 changed files with 174 additions and 108 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
zig-* zig-*
.zigmod .zigmod
deps.zig deps.zig
*.tkh

View File

@ -11,13 +11,13 @@ pub fn build(b: *std.build.Builder) void {
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
// Import autogenerated zigmod dependencies
const deps = @import("deps.zig");
const exe = b.addExecutable("mgtzm", "src/main.zig"); const exe = b.addExecutable("mgtzm", "src/main.zig");
exe.use_stage1 = true; // for sqlite exe.use_stage1 = true; // for sqlite
deps.addAllTo(exe); // zigmod dependencies
// Add dependencies
exe.linkSystemLibrary("json-c"); exe.linkSystemLibrary("json-c");
exe.linkSystemLibrary("tkrzw"); // TODO: Build statically?
exe.setTarget(target); exe.setTarget(target);
exe.setBuildMode(mode); exe.setBuildMode(mode);
exe.install(); exe.install();

View File

@ -1,78 +1,80 @@
const c = @cImport({
@cInclude("tkrzw_langc.h");
});
const Self = @This();
const std = @import("std"); const std = @import("std");
const sqlite = @import("sqlite");
// TODO: Make DB an object so we can just do Self. pub const free = c.free;
// TODO: Wrap into transactions with a .flush() method
const ObjectError = error{ dbm: *c.TkrzwDBM,
IncompatibleObjectType, // No ?u32 "id" field
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const encode_len = 4;
pub fn numEncode(num: usize) ![encode_len]u8 {
return uintEncode(num, 4, chars);
}
pub fn numDecode(str: []const u8) usize {
return uintDecode(str, chars);
}
const EncodeError = error{
NumberTooBig,
}; };
pub fn getLastId(db: *sqlite.Db) !i64 { fn uintEncode(num: usize, comptime bufflen: usize, comptime charset: []const u8) ![bufflen]u8 {
const row = try db.one( // Check if the number is bigger than the maximum possible number
struct { var pow = comptime std.math.pow(usize, charset.len, bufflen);
rowid: i64, if (num >= pow) return EncodeError.NumberTooBig;
},
"SELECT LAST_INSERT_ROWID();",
.{},
.{},
);
if (row) |row_i| { var buff = [_]u8{charset[0]} ** bufflen;
return row_i.rowid;
var num_i: usize = num;
for (buff) |*pos| {
pow /= charset.len;
pos.* = charset[@divTrunc(num_i, pow)];
num_i %= pow;
} }
return 0; return buff;
} }
pub fn init() !sqlite.Db { fn uintDecode(str: []const u8, comptime charset: []const u8) usize {
var db = try sqlite.Db.init(.{ var ret: usize = 0;
.mode = .{ .File = "/tmp/data.db" },
.open_flags = .{
.write = true,
.create = true,
},
.threading_mode = .MultiThread,
});
try migrate(&db); for (str) |needle, i| {
for (charset) |blade, j| {
if (needle == blade) {
ret += std.math.pow(usize, charset.len, str.len - i - 1) * j;
break;
}
}
}
return db; return ret;
} }
// TODO: Make a proper migration system. pub fn open(path: [:0]const u8, writable: bool, params: [:0]const u8) Self {
fn migrate(db: *sqlite.Db) !void { return Self{
try db.exec( .dbm = c.tkrzw_dbm_open(path, writable, params),
\\CREATE TABLE IF NOT EXISTS item ( };
\\ id INTEGER PRIMARY KEY }
\\);
, pub fn set(self: *Self, key: []const u8, value: []const u8) void {
.{}, const key_len = @intCast(i32, key.len);
.{}, const value_len = @intCast(i32, value.len);
);
_ = c.tkrzw_dbm_set(self.dbm, key.ptr, key_len, value.ptr, value_len, true);
try db.exec( }
\\CREATE TABLE IF NOT EXISTS tag (
\\ name TEXT PRIMARY KEY pub fn get(self: *Self, key: []const u8) []u8 {
\\); const key_len = @intCast(i32, key.len);
,
.{}, var len: i32 = 0;
.{}, var ret = c.tkrzw_dbm_get(self.dbm, key.ptr, key_len, &len);
); return ret[0..@intCast(usize, len)];
try db.exec(
\\CREATE TABLE IF NOT EXISTS item_tag (
\\ item INTEGER,
\\ tag TEXT,
\\ value TEXT,
\\
\\ PRIMARY KEY (item, tag),
\\
\\ FOREIGN KEY (item) REFERENCES item(id) ON DELETE CASCADE,
\\ FOREIGN KEY (tag) REFERENCES tag(name) ON DELETE CASCADE ON UPDATE CASCADE
\\);
,
.{},
.{},
);
} }

View File

@ -1,43 +1,68 @@
const std = @import("std"); const std = @import("std");
const sqlite = @import("sqlite");
const Db = @import("Db.zig"); const Db = @import("Db.zig");
const Item = @import("Item.zig"); const Item = @import("Item.zig");
const Tag = @import("Tag.zig"); const Tag = @import("Tag.zig");
const json = @import("json.zig"); const json = @import("json.zig");
const request = @import("request.zig"); const request = @import("request.zig");
pub fn main() !void { pub fn main() !void {
var db = try Db.init();
const jsonText: [:0]const u8 = var db = Db.open("test.tkh", true, "");
\\{ "add" : [ db.set("test", "lol");
\\ { db.set("kaka", "jeje");
\\ "fur": "dusk", db.set("kaka", "poop");
\\ "made_with": "krita",
\\ "date": "2022-10-01",
\\ "alunya": null
\\ },{
\\ "fur": "lara",
\\ "made_with": "krita",
\\ "date": "2022-04-08",
\\ "cell-shading": null
\\ },{
\\ "made_with": "ballpoint_pen",
\\ "date": "2022-11-04",
\\ "practice": "",
\\ "pose_practice": null
\\ },{
\\ "fur": "lidiarock1",
\\ "made_with": "krita",
\\ "date": "2022-02-15",
\\ "niko_(oneshot)": null
\\ }
\\] }
;
var jobj = json.Obj.newFromString(jsonText); var str = db.get("test");
defer jobj.deinit(); defer Db.free(str.ptr);
std.debug.print("{s}\n", .{str});
try request.process(&jobj, &db); const num = 69420;
const numch = try Db.numEncode(num);
std.debug.print("{}\n", .{Db.numDecode(numch[0..])});
std.debug.print("{}\n", .{num});
//var db = try Db.init();
//
//const jsonText: [:0]const u8 =
//\\{ "add" : [
//\\ {
//\\ "fur": "dusk",
//\\ "made_with": "krita",
//\\ "date": "2022-10-01",
//\\ "alunya": null
//\\ },{
//\\ "fur": "lara",
//\\ "made_with": "krita",
//\\ "date": "2022-04-08",
//\\ "cell-shading": null
//\\ },{
//\\ "made_with": "ballpoint_pen",
//\\ "date": "2022-11-04",
//\\ "practice": "",
//\\ "pose_practice": null
//\\ },{
//\\ "fur": "lidiarock1",
//\\ "made_with": "krita",
//\\ "date": "2022-02-15",
//\\ "niko_(oneshot)": null
//\\ }
//\\] }
//;
//
//var jobj = json.Obj.newFromString(jsonText);
//defer jobj.deinit();
//
//try request.process(&jobj, &db);
//
//std.debug.print("\n\n", .{});
//
//const jsonQuery: [:0]const u8 =
//\\{ "query" : "niko_(oneshot) made_with:krita -fur:dusk" }
//;
//
//var jquery = json.Obj.newFromString(jsonQuery);
//defer jquery.deinit();
//
//try request.process(&jquery, &db);
} }

View File

@ -15,11 +15,16 @@ pub fn process(jobj: *json.Obj, db: *sqlite.Db) !void {
defer jret.deinit(); defer jret.deinit();
// Test the action to carry and pass the object // Test the action to carry and pass the object
if (jobj.objectGet("add") catch null) |*jadd| { if (jobj.objectGet("add") catch null) |*jaction| {
var ret = try add(jadd, db, allocator); var ret = try add(jaction, db, allocator);
jret.objectAdd("added", &ret); jret.objectAdd("added", &ret);
} }
if (jobj.objectGet("query") catch null) |*jaction| {
var ret = try query(jaction, db, allocator);
jret.objectAdd("queried", &ret);
}
std.debug.print("{s}", .{ jret.toString() }); std.debug.print("{s}", .{ jret.toString() });
} }
@ -46,3 +51,44 @@ pub fn add(jobj: *json.Obj, db: *sqlite.Db, allocator: std.mem.Allocator) !json.
return jret; return jret;
} }
pub fn query(jobj: *json.Obj, db: *sqlite.Db, allocator: std.mem.Allocator) !json.Obj {
_ = db;
var jret = json.Obj.newArray();
const query_string = jobj.getString();
var keywords = std.ArrayList([]const u8).init(allocator);
var sql = std.ArrayList(u8).init(allocator);
try sql.appendSlice("SELECT * FROM item_tag WHERE");
var iter = std.mem.split(u8, query_string, " ");
var i: usize = 0;
while(iter.next()) |tag| {
defer i += 1;
try keywords.append(tag);
// Just put AND between keywords
if (i > 0) {
try sql.appendSlice(" AND");
}
// Exclude tags that start with !
try sql.appendSlice(" tag ");
if (tag[0] == '-') {
try sql.append('!');
}
try sql.appendSlice("= ?");
}
std.debug.print("{s}\n", .{sql.items});
//var stmt = try db.prepareDynamic();
//defer stmt.deinit();
//
return jret;
}

View File

@ -1,2 +0,0 @@
2
git https://github.com/vrischmann/zig-sqlite commit-624bbf60e79c2b6c838e952aa0c8c4cc35128044

View File

@ -1,6 +0,0 @@
id: xstmgop7lwvcrkd18q3u95noqfk3oromr3vixj1ud67rhbwl
name: uos
license: AGPLv3
description: Tagging system with a JSON API
root_dependencies:
- src: git https://github.com/vrischmann/zig-sqlite branch-master