summaryrefslogtreecommitdiff
path: root/src/duckdb/PreparedStatement.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/duckdb/PreparedStatement.zig')
-rw-r--r--src/duckdb/PreparedStatement.zig141
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);
+}