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 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
const ObjectError = error{
IncompatibleObjectType, // No ?u32 "id" field
};
pub fn getLastId(db: *sqlite.Db) !i64 {
const row = try db.one(
struct {
rowid: i64,
},
"SELECT LAST_INSERT_ROWID();",
.{},
.{},
);
if (row) |row_i| {
return row_i.rowid;
}
return 0;
}
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,
const c = @cImport({
@cInclude("tkrzw_langc.h");
});
try migrate(&db);
const Self = @This();
return db;
const std = @import("std");
pub const free = c.free;
dbm: *c.TkrzwDBM,
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const encode_len = 4;
pub fn numEncode(num: usize) ![encode_len]u8 {
return uintEncode(num, 4, chars);
}
// 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 numDecode(str: []const u8) usize {
return uintDecode(str, chars);
}
const EncodeError = error{
NumberTooBig,
};
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;
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 buff;
}
fn uintDecode(str: []const u8, comptime charset: []const u8) usize {
var ret: usize = 0;
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 ret;
}
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