Delete unused deps, implement tkrzw and num encode
This commit is contained in:
parent
9d9f297ac8
commit
895fc2b359
|
@ -1,3 +1,4 @@
|
||||||
zig-*
|
zig-*
|
||||||
.zigmod
|
.zigmod
|
||||||
deps.zig
|
deps.zig
|
||||||
|
*.tkh
|
||||||
|
|
|
@ -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();
|
||||||
|
|
146
src/Db.zig
146
src/Db.zig
|
@ -1,78 +1,80 @@
|
||||||
const std = @import("std");
|
const c = @cImport({
|
||||||
const sqlite = @import("sqlite");
|
@cInclude("tkrzw_langc.h");
|
||||||
|
|
||||||
// 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,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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.
|
pub fn numDecode(str: []const u8) usize {
|
||||||
fn migrate(db: *sqlite.Db) !void {
|
return uintDecode(str, chars);
|
||||||
try db.exec(
|
}
|
||||||
\\CREATE TABLE IF NOT EXISTS item (
|
|
||||||
\\ id INTEGER PRIMARY KEY
|
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);
|
||||||
try db.exec(
|
if (num >= pow) return EncodeError.NumberTooBig;
|
||||||
\\CREATE TABLE IF NOT EXISTS tag (
|
|
||||||
\\ name TEXT PRIMARY KEY
|
var buff = [_]u8{charset[0]} ** bufflen;
|
||||||
\\);
|
|
||||||
,
|
var num_i: usize = num;
|
||||||
.{},
|
for (buff) |*pos| {
|
||||||
.{},
|
pow /= charset.len;
|
||||||
);
|
pos.* = charset[@divTrunc(num_i, pow)];
|
||||||
|
|
||||||
try db.exec(
|
num_i %= pow;
|
||||||
\\CREATE TABLE IF NOT EXISTS item_tag (
|
}
|
||||||
\\ item INTEGER,
|
|
||||||
\\ tag TEXT,
|
return buff;
|
||||||
\\ value TEXT,
|
}
|
||||||
\\
|
|
||||||
\\ PRIMARY KEY (item, tag),
|
fn uintDecode(str: []const u8, comptime charset: []const u8) usize {
|
||||||
\\
|
var ret: usize = 0;
|
||||||
\\ FOREIGN KEY (item) REFERENCES item(id) ON DELETE CASCADE,
|
|
||||||
\\ FOREIGN KEY (tag) REFERENCES tag(name) ON DELETE CASCADE ON UPDATE CASCADE
|
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)];
|
||||||
}
|
}
|
||||||
|
|
87
src/main.zig
87
src/main.zig
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
2
|
|
||||||
git https://github.com/vrischmann/zig-sqlite commit-624bbf60e79c2b6c838e952aa0c8c4cc35128044
|
|
|
@ -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
|
|
Loading…
Reference in New Issue