diff options
| author | 2022-08-16 00:21:40 +0200 | |
|---|---|---|
| committer | 2022-09-18 20:11:36 +0200 | |
| commit | ab32ef616a520f8a727ff146df68e59d2de0a609 (patch) | |
| tree | d1cf406ac0ab14678bab54587d0b5af08f136de8 | |
| parent | move setFunctionResult to helpers.setResult (diff) | |
| download | zig-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
| -rw-r--r-- | helpers.zig | 47 | ||||
| -rw-r--r-- | sqlite.zig | 52 |
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 @@ | |||
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const debug = std.debug; | ||
| 2 | 3 | ||
| 3 | const c = @import("c.zig").c; | 4 | const 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`. | ||
| 47 | pub 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 | |||
| 81 | fn 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 | } | ||
| @@ -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); |