From 309105c7e8f43f21237dd243e714db2f16f71a6f Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Mon, 15 Aug 2022 21:52:02 +0200 Subject: move setFunctionResult to helpers.setResult This function will also be used by the virtual table implementation. --- helpers.zig | 41 +++++++++++++++++++++++++++++++++++++++++ sqlite.zig | 41 ++++------------------------------------- 2 files changed, 45 insertions(+), 37 deletions(-) create mode 100644 helpers.zig diff --git a/helpers.zig b/helpers.zig new file mode 100644 index 0000000..17a5b64 --- /dev/null +++ b/helpers.zig @@ -0,0 +1,41 @@ +const std = @import("std"); + +const c = @import("c.zig").c; + +const Blob = @import("sqlite.zig").Blob; +const Text = @import("sqlite.zig").Text; + +/// Sets the result of a function call in the context `ctx`. +/// +/// Determines at compile time which sqlite3_result_XYZ function to use based on the type of `result`. +pub fn setResult(ctx: ?*c.sqlite3_context, result: anytype) void { + const ResultType = @TypeOf(result); + + switch (ResultType) { + Text => c.sqlite3_result_text(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT), + Blob => c.sqlite3_result_blob(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT), + else => switch (@typeInfo(ResultType)) { + .Int => |info| if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 32) { + c.sqlite3_result_int(ctx, result); + } else if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 64) { + c.sqlite3_result_int64(ctx, result); + } else { + @compileError("integer " ++ @typeName(ResultType) ++ " is not representable in sqlite"); + }, + .Float => c.sqlite3_result_double(ctx, result), + .Bool => c.sqlite3_result_int(ctx, if (result) 1 else 0), + .Array => |arr| switch (arr.child) { + u8 => c.sqlite3_result_blob(ctx, &result, arr.len, c.SQLITE_TRANSIENT), + else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), + }, + .Pointer => |ptr| switch (ptr.size) { + .Slice => switch (ptr.child) { + u8 => c.sqlite3_result_text(ctx, result.ptr, @intCast(c_int, result.len), c.SQLITE_TRANSIENT), + else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), + }, + else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), + }, + else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), + }, + } +} diff --git a/sqlite.zig b/sqlite.zig index cd192a2..d0e572b 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -19,6 +19,8 @@ pub const DetailedError = errors.DetailedError; const getLastDetailedErrorFromDb = errors.getLastDetailedErrorFromDb; const getDetailedErrorFromResultCode = errors.getDetailedErrorFromResultCode; +const helpers = @import("helpers.zig"); + const logger = std.log.scoped(.sqlite); /// Text is used to represent a SQLite TEXT value when binding a parameter or reading a column. @@ -579,41 +581,6 @@ pub const Db = struct { return value.?[0..size]; } - /// Sets the result of a function call in the context `ctx`. - /// - /// Determines at compile time which sqlite3_result_XYZ function to use based on the type of `result`. - fn setFunctionResult(ctx: ?*c.sqlite3_context, result: anytype) void { - const ResultType = @TypeOf(result); - - switch (ResultType) { - Text => c.sqlite3_result_text(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT), - Blob => c.sqlite3_result_blob(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT), - else => switch (@typeInfo(ResultType)) { - .Int => |info| if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 32) { - c.sqlite3_result_int(ctx, result); - } else if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 64) { - c.sqlite3_result_int64(ctx, result); - } else { - @compileError("integer " ++ @typeName(ResultType) ++ " is not representable in sqlite"); - }, - .Float => c.sqlite3_result_double(ctx, result), - .Bool => c.sqlite3_result_int(ctx, if (result) 1 else 0), - .Array => |arr| switch (arr.child) { - u8 => c.sqlite3_result_blob(ctx, &result, arr.len, c.SQLITE_TRANSIENT), - else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), - }, - .Pointer => |ptr| switch (ptr.size) { - .Slice => switch (ptr.child) { - u8 => c.sqlite3_result_text(ctx, result.ptr, @intCast(c_int, result.len), c.SQLITE_TRANSIENT), - else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), - }, - else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), - }, - else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), - }, - } - } - /// Sets a function argument using the provided value. /// /// Determines at compile time which sqlite3_value_XYZ function to use based on the type `ArgType`. @@ -773,7 +740,7 @@ pub const Db = struct { const result = @call(.{}, finalize_func, args); - setFunctionResult(ctx, result); + helpers.setResult(ctx, result); } }.xFinal, null, @@ -830,7 +797,7 @@ pub const Db = struct { const result = @call(.{}, func, fn_args); - setFunctionResult(ctx, result); + helpers.setResult(ctx, result); } }.xFunc, null, -- cgit v1.2.3