diff options
author | Ekaitz Zarraga <ekaitz@elenq.tech> | 2024-08-01 15:46:56 +0200 |
---|---|---|
committer | Ekaitz Zarraga <ekaitz@elenq.tech> | 2024-08-01 15:46:56 +0200 |
commit | b5316c4dc3ba84a4257b996f9d1505f95fe95ab4 (patch) | |
tree | 4b30760788b20d5860f4764479fd96e731fcc60b /src/duckdb | |
parent | 9a2ed3ddf6ebbcc46d0aea394ca92b76f65e16e7 (diff) |
Separate database Result and start generics
Diffstat (limited to 'src/duckdb')
-rw-r--r-- | src/duckdb/Result.zig | 71 | ||||
-rw-r--r-- | src/duckdb/db.zig | 76 |
2 files changed, 147 insertions, 0 deletions
diff --git a/src/duckdb/Result.zig b/src/duckdb/Result.zig new file mode 100644 index 0000000..b49f704 --- /dev/null +++ b/src/duckdb/Result.zig @@ -0,0 +1,71 @@ +const std = @import("std"); +const c = @cImport({ + @cInclude("duckdb.h"); +}); + + +pub fn Result(comptime T: type) type{ + + return struct { + _res: c.duckdb_result, + _chunk: c.duckdb_data_chunk, + + const Self = @This(); + + pub fn init(conn : c.duckdb_connection, query: [:0]const u8) !Self { + var self : Self = .{ + ._res = undefined, + ._chunk = null + }; + const state = c.duckdb_query(conn, query, &self._res); + if ( state == c.DuckDBError){ + return error.DuckDBError; + } + self.fetchDataChunk(); + return self; + } + pub fn deinit(self: *Self) void { + c.duckdb_destroy_result(&self._res); + c.duckdb_destroy_data_chunk(&self._chunk); + } + + /// There's not way to know how many total elements we have, but we can + /// know how many we have in the current chunk. + fn getCurrentChunkSize(self: Self) usize { + if (self._chunk != null) { + return 0; + } + return c.duckdb_data_chunk_get_size(self._chunk); + } + + pub fn getColumnCount(self: Self) usize { + return c.duckdb_data_chunk_get_column_count(self._chunk); + } + + /// This needs to be called repeatedly to obtain the next blocks of + /// data. There's no way to know how many elements we'll obtain from + /// it. + fn fetchDataChunk(self: *Self) void{ + if (self._chunk != null){ + c.duckdb_destroy_data_chunk(&self._chunk); + } + self._chunk = c.duckdb_fetch_chunk(self._res); + } + + pub fn exausted(self: Self) bool{ + return self._chunk != null; + } + + /// We need some comptime magic to create the output structures from + /// the T. + pub fn next(self: *Self) T{ + _ = self; + const result: T = undefined; + switch (@typeInfo(T)) { + .Struct => std.debug.print("GOOOD: ", .{}), + else => null, + } + return result; + } + }; +} diff --git a/src/duckdb/db.zig b/src/duckdb/db.zig new file mode 100644 index 0000000..134a1f4 --- /dev/null +++ b/src/duckdb/db.zig @@ -0,0 +1,76 @@ +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 "Query size" { + var database = try Database.init(":memory:"); + defer database.deinit(); + var connection = try database.connect(); + defer connection.deinit(); + + const s : type = comptime struct { + primer: u8, + segund: u8 + }; + + _ = try connection.query("CREATE TABLE integers (i INTEGER, j INTEGER);", void); + _ = try connection.query("INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", void); + var result = try connection.query("SELECT * FROM integers;", s); + _ = result.next(); + defer result.deinit(); + + try std.testing.expect(2 == result.getColumnCount()); +} |