diff options
Diffstat (limited to 'src/duckdb/PreparedStatement.zig')
-rw-r--r-- | src/duckdb/PreparedStatement.zig | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/duckdb/PreparedStatement.zig b/src/duckdb/PreparedStatement.zig new file mode 100644 index 0000000..e81ac4c --- /dev/null +++ b/src/duckdb/PreparedStatement.zig @@ -0,0 +1,141 @@ +const std = @import("std"); +const c = @cImport({ + @cInclude("duckdb.h"); +}); +const Result = @import("Result.zig").Result; + +_q : c.duckdb_prepared_statement, +_current: usize, + +const Self = @This(); + +pub fn init(stmt: c.duckdb_prepared_statement) !Self{ + return .{ + ._q = stmt, + ._current = 1, + }; +} + +pub fn bindInt(self: *Self, param: anytype) !void{ + const state = switch(@TypeOf(param)) { + u8 => c.duckdb_bind_uint8 (self._q, self._current, param), + u16 => c.duckdb_bind_uint16(self._q, self._current, param), + u32 => c.duckdb_bind_uint32(self._q, self._current, param), + u64 => c.duckdb_bind_uint64(self._q, self._current, param), + i8 => c.duckdb_bind_int8 (self._q, self._current, param), + i16 => c.duckdb_bind_int16(self._q, self._current, param), + i32 => c.duckdb_bind_int32(self._q, self._current, param), + i64 => c.duckdb_bind_int64(self._q, self._current, param), + else => @compileError("Invalid int type for binding: " + ++ @typeName(@TypeOf(param))), + }; + if ( state == c.DuckDBError ) { + return error.DuckDbBindError; + } + self._current += 1; +} + +pub fn bindFloat(self: *Self, param: anytype) !void{ + const state = switch(@TypeOf(param)) { + f32 => c.duckdb_bind_float (self._q, self._current, param), + f64 => c.duckdb_bind_double(self._q, self._current, param), + else => @compileError("Invalid float type for binding: " + ++ @typeName(@TypeOf(param))), + }; + if ( state == c.DuckDBError ) { + return error.DuckDbBindError; + } + self._current += 1; +} + +pub fn bindBool(self: *Self, param: bool) !void{ + const state = c.duckdb_bind_bool(self._q, self._current, param); + if ( state == c.DuckDBError ) { + return error.DuckDbBindError; + } + self._current += 1; +} + +pub fn bindNull(self: *Self) !void{ + const state = c.duckdb_bind_bool(self._q, self._current); + if ( state == c.DuckDBError ) { + return error.DuckDbBindError; + } + self._current += 1; +} + +pub fn bindString(self: *Self, param: []const u8) !void{ + const state = c.duckdb_bind_varchar_length(self._q, self._current, + param.ptr, param.len); + if ( state == c.DuckDBError ) { + return error.DuckDbBindError; + } + self._current += 1; +} + +pub fn bind(self: *Self, param: anytype) !void { + switch (@typeInfo(@TypeOf(param))) { + .Null => return try self.bindNull(), + .Bool => return try self.bindBool(param), + .Int => return try self.bindInt(param), + .Float => return try self.bindFloat(param), + .Array => |arr| { + if (arr.child == u8){ + return try self.bindString(param); + } else { + return error.UnbindableType; + } + }, + .Pointer => |ptr| { + if (ptr.size == .Slice and ptr.child == u8){ + return try self.bindString(param); + } else { + return error.UnbindableType; + } + }, + else => @compileError("Invalid type for binding: " + ++ @typeName(@TypeOf(param))), + } +} + +pub fn bindAll(self: *Self, params: anytype) !void{ + const param_count: usize = c.duckdb_nparams(self._q); + switch (@typeInfo(@TypeOf(params))) { + .Array => |arr| { + if (arr.len == param_count){ + inline for (params) |p|{ + try self.bind(p); + } + return; + } else { + return error.BindingLengthsDoNotMatch; + } + }, + .Struct => |str|{ + const x = str.fields; + if (x.len == param_count){ + inline for (x) |field|{ + try self.bind(@field(params, field.name)); + } + return; + } else { + return error.BindingLengthsDoNotMatch; + } + }, + else => @compileError("Invalid type for binding: " + ++ @typeName(@TypeOf(params))), + } +} + +pub fn exec(self: *Self, comptime T: type) !Result(T){ + var result: c.duckdb_result = undefined; + const state = c.duckdb_execute_prepared(self._q, &result); + if ( state == c.DuckDBError ){ + return error.DuckDbExecError; + } + return try Result(T).init(result); +} + +pub fn deinit(self: *Self) void{ + c.duckdb_destroy_prepare(&self._q); +} |