const std = @import("std"); const assert = std.debug.assert; const c = @cImport({ @cInclude("duckdb.h"); }); const Result = @import("Result.zig").Result; const Connection = struct { _conn: c.duckdb_connection, pub fn init(db: Database) !Connection { var conn: Connection = undefined; if( c.duckdb_connect(db._db, &conn._conn) == c.DuckDBError ){ return error.DuckDBError; } return conn; } pub fn deinit(self: *Connection) void { c.duckdb_disconnect(&self._conn); } pub fn query(self: *Connection, q: [:0]const u8, comptime res_type: type) !Result(res_type) { return try Result(res_type).init(self._conn, q); } }; pub const Database = @This(); _db: c.duckdb_database, pub fn init(file: [*c]const u8) !Database{ var db : Database = undefined; if (c.duckdb_open(file, &db._db) == c.DuckDBError) { return error.DuckDBError; } return db; } pub fn deinit(self: *Database) void{ c.duckdb_close(&self._db); } pub fn connect(self: Database) !Connection { return Connection.init(self); } test "Open and connect" { var database = try Database.init(":memory:"); defer database.deinit(); var connection = try database.connect(); defer connection.deinit(); } test "Simple querying" { var database = try Database.init(":memory:"); defer database.deinit(); var connection = try database.connect(); defer connection.deinit(); const s : type = comptime struct { primer: i32, // This is safe because the first column is NOT NULL segund: ?i32 }; var x = try connection.query("CREATE TABLE integers (i INTEGER NOT NULL, j INTEGER);", void); x.deinit(); var y = try connection.query("INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", void); y.deinit(); var result = try connection.query("SELECT * FROM integers;", s); defer result.deinit(); try std.testing.expect(2 == result.getColumnCount()); var z = try result.next(); try std.testing.expect(z.primer == 3); try std.testing.expect(z.segund.? == 4); z = try result.next(); try std.testing.expect(z.primer == 5); try std.testing.expect(z.segund.? == 6); z = try result.next(); try std.testing.expect(z.primer == 7); try std.testing.expect(z.segund == null); } test "Checks if all fields are captured" { var database = try Database.init(":memory:"); defer database.deinit(); var connection = try database.connect(); defer connection.deinit(); const s : type = comptime struct { primer: ?i32, segund: ?i32, tercer: ?i32, }; var x = try connection.query("CREATE TABLE integers (i INTEGER NOT NULL, j INTEGER);", void); x.deinit(); var y = try connection.query("INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", void); y.deinit(); try std.testing.expectError(error.QueryColumnCountCapture, connection.query("SELECT * FROM integers;", s)); }