summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2022-08-16 00:21:40 +0200
committerGravatar Vincent Rischmann2022-09-18 20:11:36 +0200
commitab32ef616a520f8a727ff146df68e59d2de0a609 (patch)
treed1cf406ac0ab14678bab54587d0b5af08f136de8
parentmove setFunctionResult to helpers.setResult (diff)
downloadzig-sqlite-ab32ef616a520f8a727ff146df68e59d2de0a609.tar.gz
zig-sqlite-ab32ef616a520f8a727ff146df68e59d2de0a609.tar.xz
zig-sqlite-ab32ef616a520f8a727ff146df68e59d2de0a609.zip
move setFunctionArgument to helpers.setTypeFromValue
Will be used in the virtual table implementation
Diffstat (limited to '')
-rw-r--r--helpers.zig47
-rw-r--r--sqlite.zig52
2 files changed, 49 insertions, 50 deletions
diff --git a/helpers.zig b/helpers.zig
index 17a5b64..aa04f54 100644
--- a/helpers.zig
+++ b/helpers.zig
@@ -1,4 +1,5 @@
1const std = @import("std"); 1const std = @import("std");
2const debug = std.debug;
2 3
3const c = @import("c.zig").c; 4const c = @import("c.zig").c;
4 5
@@ -39,3 +40,49 @@ pub fn setResult(ctx: ?*c.sqlite3_context, result: anytype) void {
39 }, 40 },
40 } 41 }
41} 42}
43
44/// Sets a type using the provided value.
45///
46/// Determines at compile time which sqlite3_value_XYZ function to use based on the type `ArgType`.
47pub fn setTypeFromValue(comptime ArgType: type, arg: *ArgType, sqlite_value: *c.sqlite3_value) void {
48 switch (ArgType) {
49 Text => arg.*.data = sliceFromValue(sqlite_value),
50 Blob => arg.*.data = sliceFromValue(sqlite_value),
51 else => switch (@typeInfo(ArgType)) {
52 .Int => |info| if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 32) {
53 const value = c.sqlite3_value_int(sqlite_value);
54 arg.* = @intCast(ArgType, value);
55 } else if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 64) {
56 const value = c.sqlite3_value_int64(sqlite_value);
57 arg.* = @intCast(ArgType, value);
58 } else {
59 @compileError("integer " ++ @typeName(ArgType) ++ " is not representable in sqlite");
60 },
61 .Float => {
62 const value = c.sqlite3_value_double(sqlite_value);
63 arg.* = @floatCast(ArgType, value);
64 },
65 .Bool => {
66 const value = c.sqlite3_value_int(sqlite_value);
67 arg.* = value > 0;
68 },
69 .Pointer => |ptr| switch (ptr.size) {
70 .Slice => switch (ptr.child) {
71 u8 => arg.* = sliceFromValue(sqlite_value),
72 else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)),
73 },
74 else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)),
75 },
76 else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)),
77 },
78 }
79}
80
81fn sliceFromValue(sqlite_value: *c.sqlite3_value) []const u8 {
82 const size = @intCast(usize, c.sqlite3_value_bytes(sqlite_value));
83
84 const value = c.sqlite3_value_text(sqlite_value);
85 debug.assert(value != null); // TODO(vincent): how do we handle this properly ?
86
87 return value.?[0..size];
88}
diff --git a/sqlite.zig b/sqlite.zig
index 0f9078c..b7fe80f 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -570,54 +570,6 @@ pub const Db = struct {
570 return Savepoint.init(self, name); 570 return Savepoint.init(self, name);
571 } 571 }
572 572
573 // Helpers functions to implement SQLite functions.
574
575 fn sliceFromValue(sqlite_value: *c.sqlite3_value) []const u8 {
576 const size = @intCast(usize, c.sqlite3_value_bytes(sqlite_value));
577
578 const value = c.sqlite3_value_text(sqlite_value);
579 debug.assert(value != null); // TODO(vincent): how do we handle this properly ?
580
581 return value.?[0..size];
582 }
583
584 /// Sets a function argument using the provided value.
585 ///
586 /// Determines at compile time which sqlite3_value_XYZ function to use based on the type `ArgType`.
587 fn setFunctionArgument(comptime ArgType: type, arg: *ArgType, sqlite_value: *c.sqlite3_value) void {
588 switch (ArgType) {
589 Text => arg.*.data = sliceFromValue(sqlite_value),
590 Blob => arg.*.data = sliceFromValue(sqlite_value),
591 else => switch (@typeInfo(ArgType)) {
592 .Int => |info| if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 32) {
593 const value = c.sqlite3_value_int(sqlite_value);
594 arg.* = @intCast(ArgType, value);
595 } else if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 64) {
596 const value = c.sqlite3_value_int64(sqlite_value);
597 arg.* = @intCast(ArgType, value);
598 } else {
599 @compileError("integer " ++ @typeName(ArgType) ++ " is not representable in sqlite");
600 },
601 .Float => {
602 const value = c.sqlite3_value_double(sqlite_value);
603 arg.* = @floatCast(ArgType, value);
604 },
605 .Bool => {
606 const value = c.sqlite3_value_int(sqlite_value);
607 arg.* = value > 0;
608 },
609 .Pointer => |ptr| switch (ptr.size) {
610 .Slice => switch (ptr.child) {
611 u8 => arg.* = sliceFromValue(sqlite_value),
612 else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)),
613 },
614 else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)),
615 },
616 else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)),
617 },
618 }
619 }
620
621 /// CreateFunctionFlag controls the flags used when creating a custom SQL function. 573 /// CreateFunctionFlag controls the flags used when creating a custom SQL function.
622 /// See https://sqlite.org/c3ref/c_deterministic.html. 574 /// See https://sqlite.org/c3ref/c_deterministic.html.
623 /// 575 ///
@@ -725,7 +677,7 @@ pub const Db = struct {
725 const arg_ptr = &args[i + 1]; 677 const arg_ptr = &args[i + 1];
726 678
727 const ArgType = arg.arg_type.?; 679 const ArgType = arg.arg_type.?;
728 setFunctionArgument(ArgType, arg_ptr, sqlite_args[i].?); 680 helpers.setTypeFromValue(ArgType, arg_ptr, sqlite_args[i].?);
729 } 681 }
730 682
731 @call(.{}, step_func, args); 683 @call(.{}, step_func, args);
@@ -792,7 +744,7 @@ pub const Db = struct {
792 var fn_args: ArgTuple = undefined; 744 var fn_args: ArgTuple = undefined;
793 inline for (fn_info.args) |arg, i| { 745 inline for (fn_info.args) |arg, i| {
794 const ArgType = arg.arg_type.?; 746 const ArgType = arg.arg_type.?;
795 setFunctionArgument(ArgType, &fn_args[i], sqlite_args[i].?); 747 helpers.setTypeFromValue(ArgType, &fn_args[i], sqlite_args[i].?);
796 } 748 }
797 749
798 const result = @call(.{}, func, fn_args); 750 const result = @call(.{}, func, fn_args);