Delete unused deps, implement tkrzw and num encode
This commit is contained in:
parent
9d9f297ac8
commit
895fc2b359
|
@ -1,3 +1,4 @@
|
|||
zig-*
|
||||
.zigmod
|
||||
deps.zig
|
||||
*.tkh
|
||||
|
|
|
@ -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();
|
||||
|
|
146
src/Db.zig
146
src/Db.zig
|
@ -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)];
|
||||
}
|
||||
|
|
87
src/main.zig
87
src/main.zig
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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