diff options
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 35 |
1 files changed, 35 insertions, 0 deletions
| @@ -34,6 +34,7 @@ If you use this library, expect to have to make changes when you update the code | |||
| 34 | * [Allocating](#allocating-1) | 34 | * [Allocating](#allocating-1) |
| 35 | * [Bind parameters and resultset rows](#bind-parameters-and-resultset-rows) | 35 | * [Bind parameters and resultset rows](#bind-parameters-and-resultset-rows) |
| 36 | * [Custom type binding and reading](#custom-type-binding-and-reading) | 36 | * [Custom type binding and reading](#custom-type-binding-and-reading) |
| 37 | * [Note about complex allocations](#note-about-complex-allocations) | ||
| 37 | * [Comptime checks](#comptime-checks) | 38 | * [Comptime checks](#comptime-checks) |
| 38 | * [Check the number of bind parameters.](#check-the-number-of-bind-parameters) | 39 | * [Check the number of bind parameters.](#check-the-number-of-bind-parameters) |
| 39 | * [Assign types to bind markers and check them.](#assign-types-to-bind-markers-and-check-them) | 40 | * [Assign types to bind markers and check them.](#assign-types-to-bind-markers-and-check-them) |
| @@ -456,6 +457,40 @@ _NOTE_: when you _do_ allocate in `bindField` or `readField` make sure to pass a | |||
| 456 | The binding or reading code does not keep tracking of allocations made in custom types so it can't free the allocated data itself; it's therefore required | 457 | The binding or reading code does not keep tracking of allocations made in custom types so it can't free the allocated data itself; it's therefore required |
| 457 | to use an arena to prevent memory leaks. | 458 | to use an arena to prevent memory leaks. |
| 458 | 459 | ||
| 460 | ## Note about complex allocations | ||
| 461 | |||
| 462 | Depending on your queries and types there can be a lot of allocations required. Take the following example: | ||
| 463 | ```zig | ||
| 464 | const User = struct { | ||
| 465 | id: usize, | ||
| 466 | first_name: []const u8, | ||
| 467 | last_name: []const u8, | ||
| 468 | data: []const u8, | ||
| 469 | }; | ||
| 470 | |||
| 471 | fn fetchUsers(allocator: std.mem.Allocator, db: *sqlite.Db) ![]User { | ||
| 472 | var stmt = try db.prepare("SELECT id FROM user WHERE id > $id"); | ||
| 473 | defer stmt.deinit(); | ||
| 474 | |||
| 475 | return stmt.all(User, allocator, .{}, .{ .id = 20 }); | ||
| 476 | } | ||
| 477 | ``` | ||
| 478 | |||
| 479 | This will do multiple allocations: | ||
| 480 | * one for each id field in the `User` type | ||
| 481 | * one for the resulting slice | ||
| 482 | |||
| 483 | To facilitate memory handling, consider using an arena allocator like this: | ||
| 484 | ```zig | ||
| 485 | var arena = std.heap.ArenaAllocator.init(allocator); | ||
| 486 | defer arena.deinit(); | ||
| 487 | |||
| 488 | const users = try fetchUsers(arena.allocator(), db); | ||
| 489 | _ = users; | ||
| 490 | ``` | ||
| 491 | |||
| 492 | This is especially recommended if you use custom types that allocate memory since, as noted above, it's necessary to prevent memory leaks. | ||
| 493 | |||
| 459 | # Comptime checks | 494 | # Comptime checks |
| 460 | 495 | ||
| 461 | Prepared statements contain _comptime_ metadata which is used to validate every call to `exec`, `one` and `all` _at compile time_. | 496 | Prepared statements contain _comptime_ metadata which is used to validate every call to `exec`, `one` and `all` _at compile time_. |