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-*
.zigmod
deps.zig
*.tkh

View File

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

View File

@ -1,78 +1,80 @@
const c = @cImport({
@cInclude("tkrzw_langc.h");
});
const Self = @This();
const std = @import("std");
const sqlite = @import("sqlite");
// TODO: Make DB an object so we can just do Self.
// TODO: Wrap into transactions with a .flush() method
pub const free = c.free;
const ObjectError = error{
IncompatibleObjectType, // No ?u32 "id" field
dbm: *c.TkrzwDBM,
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 {
const row = try db.one(
struct {
rowid: i64,
},
"SELECT LAST_INSERT_ROWID();",
.{},
.{},
);
fn uintEncode(num: usize, comptime bufflen: usize, comptime charset: []const u8) ![bufflen]u8 {
// Check if the number is bigger than the maximum possible number
var pow = comptime std.math.pow(usize, charset.len, bufflen);
if (num >= pow) return EncodeError.NumberTooBig;
if (row) |row_i| {
return row_i.rowid;
var buff = [_]u8{charset[0]} ** bufflen;
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 {
var db = try sqlite.Db.init(.{
.mode = .{ .File = "/tmp/data.db" },
.open_flags = .{
.write = true,
.create = true,
},
.threading_mode = .MultiThread,
});
fn uintDecode(str: []const u8, comptime charset: []const u8) usize {
var ret: usize = 0;
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.
fn migrate(db: *sqlite.Db) !void {
try db.exec(
\\CREATE TABLE IF NOT EXISTS item (
\\ id INTEGER PRIMARY KEY
\\);
,
.{},
.{},
);
try db.exec(
\\CREATE TABLE IF NOT EXISTS tag (
\\ name TEXT PRIMARY KEY
\\);
,
.{},
.{},
);
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
\\);
,
.{},
.{},
);
pub fn open(path: [:0]const u8, writable: bool, params: [:0]const u8) Self {
return Self{
.dbm = c.tkrzw_dbm_open(path, writable, params),
};
}
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);
}
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)];
}

View File

@ -1,43 +1,68 @@
const std = @import("std");
const sqlite = @import("sqlite");
const Db = @import("Db.zig");
const Item = @import("Item.zig");
const Tag = @import("Tag.zig");
const json = @import("json.zig");
const request = @import("request.zig");
pub fn main() !void {
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 db = Db.open("test.tkh", true, "");
db.set("test", "lol");
db.set("kaka", "jeje");
db.set("kaka", "poop");
var jobj = json.Obj.newFromString(jsonText);
defer jobj.deinit();
var str = db.get("test");
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();
// Test the action to carry and pass the object
if (jobj.objectGet("add") catch null) |*jadd| {
var ret = try add(jadd, db, allocator);
if (jobj.objectGet("add") catch null) |*jaction| {
var ret = try add(jaction, db, allocator);
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() });
}
@ -46,3 +51,44 @@ pub fn add(jobj: *json.Obj, db: *sqlite.Db, allocator: std.mem.Allocator) !json.
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