summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md49
1 files changed, 35 insertions, 14 deletions
diff --git a/README.md b/README.md
index 07a9845..041b715 100644
--- a/README.md
+++ b/README.md
@@ -124,6 +124,8 @@ Only the `mode` field is mandatory, the other fields have sane default values.
124sqlite works exclusively by using prepared statements. The wrapper type is `sqlite.Statement`. Here is how you get one: 124sqlite works exclusively by using prepared statements. The wrapper type is `sqlite.Statement`. Here is how you get one:
125 125
126```zig 126```zig
127try db.exec("CREATE TABLE IF NOT EXISTS employees(id integer primary key, name text, age integer, salary integer)", .{}, .{});
128
127const query = 129const query =
128 \\SELECT id, name, age, salary FROM employees WHERE age > ? AND age < ? 130 \\SELECT id, name, age, salary FROM employees WHERE age > ? AND age < ?
129; 131;
@@ -153,15 +155,16 @@ For queries which do not return data (`INSERT`, `UPDATE`) you can use the `exec`
153 155
154```zig 156```zig
155const query = 157const query =
156 \\UPDATE foo SET salary = ? WHERE id = ? 158 \\INSERT INTO employees(name, age, salary) VALUES(?, ?, ?)
157; 159;
158 160
159var stmt = try db.prepare(query); 161var stmt = try db.prepare(query);
160defer stmt.deinit(); 162defer stmt.deinit();
161 163
162try stmt.exec(.{}, .{ 164try stmt.exec(.{}, .{
165 .name = "José",
166 .age = 40,
163 .salary = 20000, 167 .salary = 20000,
164 .id = 40,
165}); 168});
166``` 169```
167 170
@@ -172,7 +175,7 @@ See the section "Bind parameters and resultset rows" for more information on the
172You can reuse a statement by resetting it like this: 175You can reuse a statement by resetting it like this:
173```zig 176```zig
174const query = 177const query =
175 \\UPDATE foo SET salary = ? WHERE id = ? 178 \\UPDATE employees SET salary = ? WHERE id = ?
176; 179;
177 180
178var stmt = try db.prepare(query); 181var stmt = try db.prepare(query);
@@ -284,6 +287,8 @@ const query =
284var stmt = try db.prepare(query); 287var stmt = try db.prepare(query);
285defer stmt.deinit(); 288defer stmt.deinit();
286 289
290const allocator = std.heap.page_allocator; // Use a suitable allocator
291
287const names = try stmt.all([]const u8, allocator, .{}, .{ 292const names = try stmt.all([]const u8, allocator, .{}, .{
288 .age1 = 20, 293 .age1 = 20,
289 .age2 = 40, 294 .age2 = 40,
@@ -303,11 +308,13 @@ const query =
303var stmt = try db.prepare(query); 308var stmt = try db.prepare(query);
304defer stmt.deinit(); 309defer stmt.deinit();
305 310
311const allocator = std.heap.page_allocator; // Use a suitable allocator
312
306const row = try stmt.oneAlloc([]const u8, allocator, .{}, .{ 313const row = try stmt.oneAlloc([]const u8, allocator, .{}, .{
307 .id = 200, 314 .id = 200,
308}); 315});
309if (row) |name| { 316if (row) |name| {
310 std.log.debug("name: {}", .{name}); 317 std.log.debug("name: {s}", .{name});
311} 318}
312``` 319```
313 320
@@ -326,7 +333,7 @@ Iterating is done by calling the `next` or `nextAlloc` method on an iterator. Ju
326### `Iterator.next` 333### `Iterator.next`
327 334
328```zig 335```zig
329var stmt = try db.prepare("SELECT age FROM user WHERE age < ?"); 336var stmt = try db.prepare("SELECT age FROM employees WHERE age < ?");
330defer stmt.deinit(); 337defer stmt.deinit();
331 338
332var iter = try stmt.iterator(usize, .{ 339var iter = try stmt.iterator(usize, .{
@@ -341,19 +348,21 @@ while (try iter.next(.{})) |age| {
341### `Iterator.nextAlloc` 348### `Iterator.nextAlloc`
342 349
343```zig 350```zig
344var stmt = try db.prepare("SELECT name FROM user WHERE age < ?"); 351var stmt = try db.prepare("SELECT name FROM employees WHERE age < ?");
345defer stmt.deinit(); 352defer stmt.deinit();
346 353
347var iter = try stmt.iterator([]const u8, .{ 354var iter = try stmt.iterator([]const u8, .{
348 .age = 20, 355 .age = 20,
349}); 356});
350 357
358const allocator = std.heap.page_allocator; // Use a suitable allocator
359
351while (true) { 360while (true) {
352 var arena = std.heap.ArenaAllocator.init(allocator); 361 var arena = std.heap.ArenaAllocator.init(allocator);
353 defer arena.deinit(); 362 defer arena.deinit();
354 363
355 const name = (try iter.nextAlloc(arena.allocator(), .{})) orelse break; 364 const name = (try iter.nextAlloc(arena.allocator(), .{})) orelse break;
356 std.debug.print("name: {}\n", .{name}); 365 std.debug.print("name: {s}\n", .{name});
357} 366}
358``` 367```
359 368
@@ -438,6 +447,8 @@ This will do multiple allocations:
438 447
439To facilitate memory handling, consider using an arena allocator like this: 448To facilitate memory handling, consider using an arena allocator like this:
440```zig 449```zig
450const allocator = std.heap.page_allocator; // Use a suitable allocator
451
441var arena = std.heap.ArenaAllocator.init(allocator); 452var arena = std.heap.ArenaAllocator.init(allocator);
442defer arena.deinit(); 453defer arena.deinit();
443 454
@@ -460,7 +471,9 @@ Take the following code:
460var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?"); 471var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?");
461defer stmt.deinit(); 472defer stmt.deinit();
462 473
463const rows = try stmt.all(usize, .{}, .{ 474const allocator = std.heap.page_allocator; // Use a suitable allocator
475
476const rows = try stmt.all(usize, allocator, .{}, .{
464 .age_1 = 10, 477 .age_1 = 10,
465 .age_2 = 20, 478 .age_2 = 20,
466}); 479});
@@ -495,7 +508,9 @@ For example, take the same code as above but now we also bind the last parameter
495var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?"); 508var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?");
496defer stmt.deinit(); 509defer stmt.deinit();
497 510
498const rows = try stmt.all(usize, .{ .allocator = allocator }, .{ 511const allocator = std.heap.page_allocator; // Use a suitable allocator
512
513const rows = try stmt.all(usize, allocator, .{}, .{
499 .age_1 = 10, 514 .age_1 = 10,
500 .age_2 = 20, 515 .age_2 = 20,
501 .weight = false, 516 .weight = false,
@@ -510,7 +525,9 @@ We can make sure the bind parameters have the right type if we rewrite the query
510var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?{usize}"); 525var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?{usize}");
511defer stmt.deinit(); 526defer stmt.deinit();
512 527
513const rows = try stmt.all(usize, .{ .allocator = allocator }, .{ 528const allocator = std.heap.page_allocator; // Use a suitable allocator
529
530const rows = try stmt.all(usize, allocator, .{}, .{
514 .age_1 = 10, 531 .age_1 = 10,
515 .age_2 = 20, 532 .age_2 = 20,
516 .weight = false, 533 .weight = false,
@@ -554,7 +571,9 @@ To finish our example, passing the proper type allows it compile:
554var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?{usize}"); 571var stmt = try db.prepare("SELECT id FROM user WHERE age > ? AND age < ? AND weight > ?{usize}");
555defer stmt.deinit(); 572defer stmt.deinit();
556 573
557const rows = try stmt.all(usize, .{}, .{ 574const allocator = std.heap.page_allocator; // Use a suitable allocator
575
576const rows = try stmt.all(usize, allocator, .{}, .{
558 .age_1 = 10, 577 .age_1 = 10,
559 .age_2 = 20, 578 .age_2 = 20,
560 .weight = @as(usize, 200), 579 .weight = @as(usize, 200),
@@ -597,7 +616,7 @@ Each input arguments in the function call in the statement is passed on to the r
597 616
598## Aggregate functions 617## Aggregate functions
599 618
600You can define a scalar function using `db.createAggregateFunction`: 619You can define a aggregate function using `db.createAggregateFunction`:
601```zig 620```zig
602const MyContext = struct { 621const MyContext = struct {
603 sum: u32, 622 sum: u32,
@@ -608,12 +627,14 @@ try db.createAggregateFunction(
608 "mySum", 627 "mySum",
609 &my_ctx, 628 &my_ctx,
610 struct { 629 struct {
611 fn step(ctx: *MyContext, input: u32) void { 630 fn step(fctx: sqlite.FunctionContext, input: u32) void {
631 var ctx = fctx.userContext(*MyContext) orelse return;
612 ctx.sum += input; 632 ctx.sum += input;
613 } 633 }
614 }.step, 634 }.step,
615 struct { 635 struct {
616 fn finalize(ctx: *MyContext) u32 { 636 fn finalize(fctx: sqlite.FunctionContext) u32 {
637 const ctx = fctx.userContext(*MyContext) orelse return 0;
617 return ctx.sum; 638 return ctx.sum;
618 } 639 }
619 }.finalize, 640 }.finalize,