Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/SQLite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,9 @@ function sqlitevalue(::Type{T}, handle, col)::T where {T<:FLOAT_TYPES}
end
#TODO: test returning a WeakRefString instead of calling `unsafe_string`
function sqlitevalue(::Type{T}, handle, col)::T where {T<:AbstractString}
convert(T, unsafe_string(C.sqlite3_column_text(handle, col - 1)))
text = C.sqlite3_column_text(handle, col - 1)
nbytes = C.sqlite3_column_bytes(handle, col - 1)
convert(T, unsafe_string(text, nbytes))
end
function sqlitevalue(::Type{T}, handle, col) where {T}
blob = convert(Ptr{UInt8}, C.sqlite3_column_blob(handle, col - 1))
Expand Down
4 changes: 3 additions & 1 deletion src/UDF.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ function sqlvalue(values, i)
elseif valuetype == C.SQLITE_FLOAT
return C.sqlite3_value_double(temp_val_ptr)
elseif valuetype == C.SQLITE_TEXT
return unsafe_string(C.sqlite3_value_text(temp_val_ptr))
text = C.sqlite3_value_text(temp_val_ptr)
nbytes = C.sqlite3_value_bytes(temp_val_ptr)
return unsafe_string(text, nbytes)
elseif valuetype == C.SQLITE_BLOB
nbytes = C.sqlite3_value_bytes(temp_val_ptr)
blob = C.sqlite3_value_blob(temp_val_ptr)
Expand Down
36 changes: 36 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,42 @@ end
DBInterface.close!(db)
end

@testset "TEXT byte lengths" begin
values = [missing, "", "plain", "é🚀", "\0", "\0lead", "tail\0", "a\0b\0c", "é\0🚀"]
expected_bytes = [ismissing(v) ? missing : ncodeunits(v) for v in values]
expected_hex = [ismissing(v) ? "" : uppercase(bytes2hex(codeunits(v))) for v in values]
db = SQLite.DB()
saved_values = []
try
SQLite.execute(db, "CREATE TABLE text_values (value TEXT)")
insert = SQLite.Stmt(db, "INSERT INTO text_values VALUES (?)")
for value in values
SQLite.execute(insert, (value,))
end
SQLite.register(db, v -> ismissing(v) ? missing : ncodeunits(v);
name = "text_bytes", nargs = 1)
SQLite.register(db, 0, (n, v) -> n + (ismissing(v) ? 0 : ncodeunits(v));
name = "total_text_bytes", nargs = 1)
select = SQLite.Stmt(db,
"SELECT value, hex(value) AS bytes, text_bytes(value) AS byte_count FROM text_values ORDER BY rowid")
for strict in (false, true)
result = Tables.columntable(DBInterface.execute(select, (); strict = strict))
@test isequal(result.value, values)
@test result.bytes == expected_hex
@test isequal(result.byte_count, expected_bytes)
push!(saved_values, result.value)
end
result = DBInterface.execute(columntable, db,
"SELECT total_text_bytes(value) AS n FROM text_values")
@test only(result.n) == sum(skipmissing(expected_bytes))
finally
close(db)
end
for result in saved_values
@test isequal(result, values)
end
end

@testset "Julia to SQLite3 type conversion" begin
@test SQLite.sqlitetype(Int) == "INT NOT NULL"
@test SQLite.sqlitetype(Union{Float64,Missing}) == "REAL"
Expand Down
Loading