comptime sql bindings for zig
ziglang sql

rewrite readme for clarity

- lead with usage example
- "why" section explains injection prevention by construction
- concise feature table
- cleaner install instructions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+28 -30
+28 -30
README.md
··· 1 # zql 2 3 - comptime sql ergonomics for zig. **alpha** - api may change. 4 - 5 - ## features 6 - 7 - - **named parameters**: `:name` syntax with comptime validation 8 - - **column extraction**: parse SELECT columns at comptime 9 - - **struct mapping**: map rows to structs with comptime validation 10 - - **zero runtime overhead**: all parsing happens at compile time 11 - 12 - ## usage 13 14 ```zig 15 - const zql = @import("zql"); 16 17 - const Q = zql.Query("SELECT id, name, age FROM users WHERE age > :min_age"); 18 19 - // access parsed metadata 20 - _ = Q.raw; // original sql 21 - _ = Q.positional; // "SELECT id, name, age FROM users WHERE age > ?" 22 - _ = Q.params; // ["min_age"] 23 - _ = Q.columns; // ["id", "name", "age"] 24 25 - // comptime validation 26 - Q.validateArgs(struct { min_age: i64 }); // error if param missing 27 - Q.validateStruct(User); // error if field not in columns 28 29 - // struct mapping (with any row type that has .get(idx)) 30 - const User = struct { id: i64, name: []const u8 }; 31 - const user = Q.fromRow(User, row_data); 32 33 - // column index lookup 34 - const idx = Q.columnIndex("name"); // 1 35 ``` 36 37 ## install 38 39 ```zig 40 // build.zig.zon 41 - .dependencies = .{ 42 - .zql = .{ 43 - .url = "https://github.com/zzstoatzz/zql/archive/main.tar.gz", 44 - }, 45 }, 46 ``` 47 48 ## status 49 50 - alpha. contributions welcome.
··· 1 # zql 2 3 + comptime sql bindings for zig. 4 5 ```zig 6 + const Q = zql.Query("SELECT id, name FROM users WHERE id = :id"); 7 8 + // named params -> prepared statement 9 + db.query(Q.positional, Q.bind(.{ .id = user_id })); 10 11 + // type-safe row mapping 12 + const user = Q.fromRow(User, row); 13 + ``` 14 15 + ## why 16 17 + sql injection is prevented by construction. the sql string is comptime - you can't concatenate runtime values into it. parameters are bound separately via prepared statements. 18 19 + ```zig 20 + // this doesn't compile - user_input isn't comptime 21 + const Q = zql.Query("SELECT * FROM users WHERE id = '" ++ user_input ++ "'"); 22 ``` 23 24 + ## features 25 + 26 + | feature | what it does | 27 + |---------|--------------| 28 + | `Q.positional` | sql with `:name` converted to `?` | 29 + | `Q.bind(.{...})` | struct args → tuple in param order | 30 + | `Q.columns` | column names extracted from SELECT | 31 + | `Q.fromRow(T, row)` | map row to struct with comptime validation | 32 + 33 ## install 34 35 ```zig 36 // build.zig.zon 37 + .zql = .{ 38 + .url = "https://github.com/zzstoatzz/zql/archive/main.tar.gz", 39 + .hash = "...", // zig build will tell you 40 }, 41 + 42 + // build.zig 43 + exe.root_module.addImport("zql", b.dependency("zql", .{}).module("zql")); 44 ``` 45 46 ## status 47 48 + alpha. api may change.