Skip to content
Open
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
8 changes: 4 additions & 4 deletions src/SQLite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ mutable struct Stmt <: DBInterface.Statement
end
end

_get_stmt_handle(stmt::Stmt) = stmt.stmt_wrapper[]
_get_stmt_handle(stmt::Stmt)::StmtHandle = stmt.stmt_wrapper[]
function _set_stmt_handle(stmt::Stmt, handle)
stmt.stmt_wrapper[] = handle
end
Expand Down Expand Up @@ -484,15 +484,15 @@ function sqlitevalue(
::Type{T},
handle,
col,
) where {T<:Union{Base.BitSigned,Base.BitUnsigned}}
)::T where {T<:Union{Base.BitSigned,Base.BitUnsigned}}
convert(T, C.sqlite3_column_int64(handle, col - 1))
end
const FLOAT_TYPES = Union{Float16,Float32,Float64} # exclude BigFloat
function sqlitevalue(::Type{T}, handle, col) where {T<:FLOAT_TYPES}
function sqlitevalue(::Type{T}, handle, col)::T where {T<:FLOAT_TYPES}
convert(T, C.sqlite3_column_double(handle, col - 1))
end
#TODO: test returning a WeakRefString instead of calling `unsafe_string`
function sqlitevalue(::Type{T}, handle, col) where {T<:AbstractString}
function sqlitevalue(::Type{T}, handle, col)::T where {T<:AbstractString}
convert(T, unsafe_string(C.sqlite3_column_text(handle, col - 1)))
end
function sqlitevalue(::Type{T}, handle, col) where {T}
Expand Down
30 changes: 19 additions & 11 deletions src/tables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,26 +78,34 @@ end
end

function getvalue(
q::Query{strict},
q::Query{true},
col::Int,
rownumber::Int,
::Type{T},
) where {strict,T}
)::Union{Missing,nonmissingtype(T)} where {T}
rownumber == q.current_rownumber[] || wrongrow(rownumber)
handle = _get_stmt_handle(q.stmt)
t = C.sqlite3_column_type(handle, col - 1)
if t == C.SQLITE_NULL
return missing
end
sqlitevalue(nonmissingtype(T), handle, col)
end

function getvalue(
q::Query{false},
col::Int,
rownumber::Int,
::Type{T},
) where {T}
rownumber == q.current_rownumber[] || wrongrow(rownumber)
handle = _get_stmt_handle(q.stmt)
t = C.sqlite3_column_type(handle, col - 1)
if t == C.SQLITE_NULL
return missing
elseif strict
return sqlitevalue(T, handle, col)
else
TT = juliatype(t) # native SQLite Int, Float, and Text types
return sqlitevalue(
ifelse(TT === Any && !isbitstype(T), T, TT),
handle,
col,
)
end
TT = juliatype(t) # native SQLite Int, Float, and Text types
return sqlitevalue(ifelse(TT === Any && !isbitstype(T), T, TT), handle, col)
end

function Tables.getcolumn(r::Row, ::Type{T}, i::Int, nm::Symbol) where {T}
Expand Down
42 changes: 42 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,48 @@ end
tbl = DBInterface.execute(db, "select x from tmp") |> columntable
@test isequal(tbl.x, [missing, :a])

# Symbol in TEXT type doesn't work
# when strict and first row is NULL
tbl =
DBInterface.execute(
DBInterface.prepare(db, "select x from tmp"),
();
strict = true,
) |> columntable
@test isequal(tbl.x, [missing, "7JL\x1e\x04"])

# Symbol in BLOB type does work strict
db = SQLite.DB()
DBInterface.execute(db, "create table tmp ( x BLOB )")
DBInterface.execute(db, "insert into tmp values (?)", (nothing,))
DBInterface.execute(db, "insert into tmp values (?)", (:a,))
tbl = DBInterface.execute(db, "select x from tmp") |> columntable
@test isequal(tbl.x, [missing, :a])

tbl =
DBInterface.execute(
DBInterface.prepare(db, "select x from tmp"),
();
strict = true,
) |> columntable
@test isequal(tbl.x, [missing, :a])

# Symbol in TEXT always works when first row is not NULL
db = SQLite.DB()
DBInterface.execute(db, "create table tmp ( x TEXT )")
DBInterface.execute(db, "insert into tmp values (?)", (:a,))
DBInterface.execute(db, "insert into tmp values (?)", (nothing,))
tbl = DBInterface.execute(db, "select x from tmp") |> columntable
@test isequal(tbl.x, [:a, missing])

tbl =
DBInterface.execute(
DBInterface.prepare(db, "select x from tmp"),
();
strict = true,
) |> columntable
@test isequal(tbl.x, [:a, missing])

db = SQLite.DB()
DBInterface.execute(
db,
Expand Down