summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2022-08-15 21:52:02 +0200
committerGravatar Vincent Rischmann2022-09-18 20:11:36 +0200
commitdc869b6b3e885a0f7067c09963ce5adff8e1d746 (patch)
treed809a043740a63ac94342955e31e81116a03103f
parentci: test the loadable extension (diff)
downloadzig-sqlite-dc869b6b3e885a0f7067c09963ce5adff8e1d746.tar.gz
zig-sqlite-dc869b6b3e885a0f7067c09963ce5adff8e1d746.tar.xz
zig-sqlite-dc869b6b3e885a0f7067c09963ce5adff8e1d746.zip
move setFunctionResult to helpers.setResult
This function will also be used by the virtual table implementation.
Diffstat (limited to '')
-rw-r--r--helpers.zig41
-rw-r--r--sqlite.zig41
2 files changed, 45 insertions, 37 deletions
diff --git a/helpers.zig b/helpers.zig
new file mode 100644
index 0000000..17a5b64
--- /dev/null
+++ b/helpers.zig
@@ -0,0 +1,41 @@
1const std = @import("std");
2
3const c = @import("c.zig").c;
4
5const Blob = @import("sqlite.zig").Blob;
6const Text = @import("sqlite.zig").Text;
7
8/// Sets the result of a function call in the context `ctx`.
9///
10/// Determines at compile time which sqlite3_result_XYZ function to use based on the type of `result`.
11pub fn setResult(ctx: ?*c.sqlite3_context, result: anytype) void {
12 const ResultType = @TypeOf(result);
13
14 switch (ResultType) {
15 Text => c.sqlite3_result_text(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT),
16 Blob => c.sqlite3_result_blob(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT),
17 else => switch (@typeInfo(ResultType)) {
18 .Int => |info| if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 32) {
19 c.sqlite3_result_int(ctx, result);
20 } else if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 64) {
21 c.sqlite3_result_int64(ctx, result);
22 } else {
23 @compileError("integer " ++ @typeName(ResultType) ++ " is not representable in sqlite");
24 },
25 .Float => c.sqlite3_result_double(ctx, result),
26 .Bool => c.sqlite3_result_int(ctx, if (result) 1 else 0),
27 .Array => |arr| switch (arr.child) {
28 u8 => c.sqlite3_result_blob(ctx, &result, arr.len, c.SQLITE_TRANSIENT),
29 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
30 },
31 .Pointer => |ptr| switch (ptr.size) {
32 .Slice => switch (ptr.child) {
33 u8 => c.sqlite3_result_text(ctx, result.ptr, @intCast(c_int, result.len), c.SQLITE_TRANSIENT),
34 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
35 },
36 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
37 },
38 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
39 },
40 }
41}
diff --git a/sqlite.zig b/sqlite.zig
index 98f59bc..0f9078c 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -19,6 +19,8 @@ pub const DetailedError = errors.DetailedError;
19const getLastDetailedErrorFromDb = errors.getLastDetailedErrorFromDb; 19const getLastDetailedErrorFromDb = errors.getLastDetailedErrorFromDb;
20const getDetailedErrorFromResultCode = errors.getDetailedErrorFromResultCode; 20const getDetailedErrorFromResultCode = errors.getDetailedErrorFromResultCode;
21 21
22const helpers = @import("helpers.zig");
23
22const logger = std.log.scoped(.sqlite); 24const logger = std.log.scoped(.sqlite);
23 25
24/// Text is used to represent a SQLite TEXT value when binding a parameter or reading a column. 26/// 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 {
579 return value.?[0..size]; 581 return value.?[0..size];
580 } 582 }
581 583
582 /// Sets the result of a function call in the context `ctx`.
583 ///
584 /// Determines at compile time which sqlite3_result_XYZ function to use based on the type of `result`.
585 fn setFunctionResult(ctx: ?*c.sqlite3_context, result: anytype) void {
586 const ResultType = @TypeOf(result);
587
588 switch (ResultType) {
589 Text => c.sqlite3_result_text(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT),
590 Blob => c.sqlite3_result_blob(ctx, result.data.ptr, @intCast(c_int, result.data.len), c.SQLITE_TRANSIENT),
591 else => switch (@typeInfo(ResultType)) {
592 .Int => |info| if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 32) {
593 c.sqlite3_result_int(ctx, result);
594 } else if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 64) {
595 c.sqlite3_result_int64(ctx, result);
596 } else {
597 @compileError("integer " ++ @typeName(ResultType) ++ " is not representable in sqlite");
598 },
599 .Float => c.sqlite3_result_double(ctx, result),
600 .Bool => c.sqlite3_result_int(ctx, if (result) 1 else 0),
601 .Array => |arr| switch (arr.child) {
602 u8 => c.sqlite3_result_blob(ctx, &result, arr.len, c.SQLITE_TRANSIENT),
603 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
604 },
605 .Pointer => |ptr| switch (ptr.size) {
606 .Slice => switch (ptr.child) {
607 u8 => c.sqlite3_result_text(ctx, result.ptr, @intCast(c_int, result.len), c.SQLITE_TRANSIENT),
608 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
609 },
610 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
611 },
612 else => @compileError("cannot use a result of type " ++ @typeName(ResultType)),
613 },
614 }
615 }
616
617 /// Sets a function argument using the provided value. 584 /// Sets a function argument using the provided value.
618 /// 585 ///
619 /// Determines at compile time which sqlite3_value_XYZ function to use based on the type `ArgType`. 586 /// Determines at compile time which sqlite3_value_XYZ function to use based on the type `ArgType`.
@@ -773,7 +740,7 @@ pub const Db = struct {
773 740
774 const result = @call(.{}, finalize_func, args); 741 const result = @call(.{}, finalize_func, args);
775 742
776 setFunctionResult(ctx, result); 743 helpers.setResult(ctx, result);
777 } 744 }
778 }.xFinal, 745 }.xFinal,
779 null, 746 null,
@@ -830,7 +797,7 @@ pub const Db = struct {
830 797
831 const result = @call(.{}, func, fn_args); 798 const result = @call(.{}, func, fn_args);
832 799
833 setFunctionResult(ctx, result); 800 helpers.setResult(ctx, result);
834 } 801 }
835 }.xFunc, 802 }.xFunc,
836 null, 803 null,