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; } }; }