From a4c6b80b31bd10a26f40eec19d2bd77a83917315 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Sun, 25 Oct 2020 00:05:24 +0200 Subject: add readme --- README.md | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 README.md (limited to 'README.md') diff --git a/README.md b/README.md new file mode 100644 index 0000000..658498e --- /dev/null +++ b/README.md @@ -0,0 +1,122 @@ +# zig-sqlite + +This package is a thin wrapper around [sqlite](https://sqlite.org/index.html)'s C API. + +## Requirements + +* Linux +* the system and development package for sqlite + * `libsqlite3-dev` for Debian and derivatives + * `sqlite3-devel` for Fedora + +## Installation + +Since there's no package manager for Zig yet, the recommended way is to use a git submodule: + + $ git submodule add https://git.sr.ht/~vrischmann/zig-sqlite src/sqlite + +Then add the following to your `build.zig` target(s): + + exe.linkLibC(); + exe.linkSystemLibrary("sqlite3"); + exe.addPackage(.{ .name = "sqlite", .path = "src/sqlite/sqlite.zig" }); + +Now you should be able to import sqlite like this: + + const sqlite = @import("sqlite"); + +## Usage + +### Initialization + +You must create and initialize an instance of `sqlite.Db`: + + var db: sqlite.Db = undefined; + try db.init(allocator, .{ .mode = sqlite.Db.Mode{ .File = "/home/vincent/mydata.db" } }); + +The `init` method takes an allocator and an optional tuple which will used to configure sqlite. + +Right now the only member used in that tuple is `mode` which defines if the sqlite database is in memory or uses a file. + +### Preparing a statement + +sqlite works exclusively by using prepared statements. The wrapper type is `sqlite.Statement`. Here is how you get one: + + const query = + \\SELECT id, name, age, salary FROM employees WHERE age > ? AND age < ? + ; + + var stmt = try db.prepare(query, .{ + .age1 = 20, + .age2 = 40, + }); + defer stmt.deinit(); + +The `Db.prepare` method takes a `comptime` query string and a tuple of bind parameters. + +The number of bind parameters is comptime checked against the number of bind markers in the query string, so if you have 2 bind markers +you must provide 2 bind parameters. + +Note that the fields name is irrelevant, only their order is relevant. + +See the section "Bind parameters and resultset rows" for more information on the types mapping rules. + +### Executing a statement + +For queries which do not return data (`INSERT`, `UPDATE`) you can use the `exec` method: + + const query = + \\UPDATE foo SET salary = ? WHERE id = ? + ; + + var stmt = try db.prepare(query, .{ + .salary = 20000, + .id = 40, + }); + defer stmt.deinit(); + + try stmt.exec(); + +### Reading data + +For queries which do return data you can use the `all` method: + + const query = + \\SELECT id, name, age, salary FROM employees WHERE age > ? AND age < ? + ; + + var stmt = try db.prepare(query, .{ + .age1 = 20, + .age2 = 40, + }); + defer stmt.deinit(); + + const rows = try stmt.all( + struct { + id: usize, + name: []const u8, + age: u16, + salary: u32, + }, + .{ .allocator = allocator }, + ); + for (rows) |row| { + std.log.debug("id: {} ; name: {}; age: {}; salary: {}", .{ row.id, row.name, row.age, row.salary }); + } + +The `all` method takes a type and an optional tuple. + +The type represents a "row", it can be: +* a struct where each field maps to the corresponding column in the resultset (so field 0 must map to field 1 and so on). +* a single type, in that case the resultset must only return one column. + +Not all types are allowed, see the section "Bind parameters and resultset rows" for more information on the types mapping rules. + +### Bind parameters and resultset rows + +Since sqlite doesn't have many [types](https://www.sqlite.org/datatype3.html) only a small number of Zig types are allowed in binding parameters and in resultset mapping types. + +Here are the rules for bind parameters: +* any Zig `Int` or `ComptimeInt` is tread as a `INTEGER`. +* any Zig `Float` or `ComptimeFloat` is treated as a `REAL`. +* `[]const u8`, `[]u8` or any array of `u8` is treated as a `TEXT` or `BLOB`. -- cgit v1.2.3