@@ -1154,6 +1154,74 @@ end
11541154 end
11551155 end
11561156
1157+ @testset " UDF value marshalling" begin
1158+ # These tests pin down SQLite.sqlvalue, which unmarshals a C
1159+ # sqlite3_value* into a Julia value on the UDF argument hot path. A
1160+ # registered `identity` UDF forces every argument through sqlvalue on
1161+ # the way in and sqlreturn on the way out, so `roundtrip(x)` exercises
1162+ # both marshalling directions for a single value and lets us assert
1163+ # exact round-trip equality. The Int64-boundary cases in particular
1164+ # cover the `Sys.WORD_SIZE == 64` branch of sqlvalue: on a 64-bit build
1165+ # the value must be read with sqlite3_value_int64; sqlite3_value_int
1166+ # would silently truncate anything outside the Int32 range.
1167+ db = SQLite. DB ()
1168+ SQLite. register (db, identity; nargs = 1 , name = " roundtrip" )
1169+
1170+ roundtrip (v) = first (
1171+ DBInterface. execute (db, " SELECT roundtrip(?) AS v" , (v,)) |>
1172+ columntable |>
1173+ t -> t. v,
1174+ )
1175+
1176+ @testset " Int64 boundary integers" begin
1177+ for v in (
1178+ typemax (Int64),
1179+ typemin (Int64),
1180+ Int64 (2 )^ 40 ,
1181+ Int64 (2 )^ 31 , # first value past Int32 max
1182+ Int64 (2 )^ 31 - 1 , # Int32 max itself
1183+ - (Int64 (2 )^ 31 ) - 1 , # first value below Int32 min
1184+ 0 ,
1185+ 1 ,
1186+ - 1 ,
1187+ 42 ,
1188+ - 42 ,
1189+ )
1190+ got = roundtrip (v)
1191+ @test got isa Int64
1192+ @test got == v
1193+ end
1194+ end
1195+
1196+ @testset " Float64 values" begin
1197+ for v in (0.0 , 3.5 , - 2.25 , 6.4 , floatmax (Float64))
1198+ got = roundtrip (v)
1199+ @test got isa Float64
1200+ @test got == v
1201+ end
1202+ end
1203+
1204+ @testset " String values" begin
1205+ # includes multi-byte UTF-8: sqlite3_value_text returns bytes, so
1206+ # codeunit/character confusion would corrupt non-ASCII round-trips
1207+ for v in (" " , " abc" , " a longer string with spaces" , " příliš žluťoučký kůň 🐎 ∀x" )
1208+ got = roundtrip (v)
1209+ @test got isa String
1210+ @test got == v
1211+ end
1212+ end
1213+
1214+ @testset " blob values" begin
1215+ v = UInt8[0x00 , 0x01 , 0xfe , 0xff ]
1216+ got = roundtrip (v)
1217+ @test got == v
1218+ end
1219+
1220+ @testset " NULL value" begin
1221+ @test roundtrip (missing ) === missing
1222+ end
1223+ end
1224+
11571225 @testset " serialization" begin
11581226 @testset " serialization edgecases" begin
11591227 db = SQLite. DB ()
0 commit comments