Skip to content

Commit a0c7864

Browse files
committed
renaming, style
1 parent e4237ef commit a0c7864

1 file changed

Lines changed: 106 additions & 71 deletions

File tree

src/QuerySQLite.jl

Lines changed: 106 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
module QuerySQLite
22

3-
import Base: !, &, |, ==, !=, coalesce, getproperty, in, isequal, isless, ismissing, occursin, startswith
4-
using Base: Generator, NamedTuple, tail
3+
import Base: !, &, |, ==, !=, coalesce, collect, eltype, getproperty, in,
4+
isdone, isequal, isless, ismissing, iterate, IteratorSize, occursin, show,
5+
startswith
6+
using Base: Generator, NamedTuple, RefValue, SizeUnknown, tail
57
import Base.Iterators: drop, take
68
using Base.Meta: quot
9+
import Base.Multimedia: showable
10+
using DataValues: DataValue
11+
import IteratorInterfaceExtensions: getiterator, isiterable
712
import MacroTools
813
using MacroTools: @capture
914
import QueryOperators
1015
import QueryOperators: orderby, query
1116
import SQLite
12-
using SQLite: columns, DB, tables
13-
import IteratorInterfaceExtensions, TableTraits
14-
using DataValues
15-
import TableShowUtils
17+
import SQLite: getvalue
18+
using SQLite: columns, DB, execute!, generate_namedtuple, juliatype,
19+
SQLITE_DONE, SQLITE_NULL, SQLITE_ROW, sqlite3_column_count, sqlite3_column_name,
20+
sqlite3_column_type, sqlite3_step, sqlitevalue, Stmt, tables
21+
using TableShowUtils: printdataresource, printHTMLtable, printtable
22+
import TableTraits: isiterabletable
1623

1724
map_unrolled(call, variables::Tuple{}) = ()
1825
map_unrolled(call, variables) =
@@ -412,7 +419,7 @@ translate(code::Expr) =
412419
end, arguments...)
413420
elseif @capture code left_ && right_
414421
translate_call(&, left, right)
415-
elseif @capture code left_ | right_
422+
elseif @capture code left_ || right_
416423
translate_call(|, left, right)
417424
elseif @capture code if condition_ yes_ else no_ end
418425
translate_call(if_else, condition, left, right)
@@ -423,90 +430,118 @@ translate(code::Expr) =
423430
# collect
424431
query(outside_code::OutsideCode) = outside_code
425432

426-
struct SQLiteCursor{T}
427-
stmt::SQLite.Stmt
428-
status::Base.RefValue{Cint}
429-
cur_row::Base.RefValue{Int}
433+
struct SQLiteCursor{Row}
434+
statement::Stmt
435+
status::RefValue{Cint}
436+
cursor_row::RefValue{Int}
430437
end
431438

432-
Base.eltype(q::SQLiteCursor{T}) where {T} = T
433-
Base.IteratorSize(::Type{<:SQLiteCursor}) = Base.SizeUnknown()
434-
435-
function isdone(q::SQLiteCursor)
436-
st = q.status[]
437-
st == SQLite.SQLITE_DONE && return true
438-
st == SQLite.SQLITE_ROW || SQLite.sqliteerror(q.stmt.db)
439-
return false
439+
eltype(::SQLiteCursor{Row}) where {Row} = Row
440+
IteratorSize(::Type{<:SQLiteCursor}) = SizeUnknown()
441+
442+
function isdone(cursor::SQLiteCursor)
443+
status = cursor.status[]
444+
if status == SQLITE_DONE
445+
true
446+
elseif status == SQLITE_ROW
447+
false
448+
elseif sqliteerror(cursor.statement.db)
449+
false
450+
else
451+
error("Unknown SQLite cursor status")
452+
end
440453
end
441454

442-
function SQLite.getvalue(q::SQLiteCursor, col::Int, ::Type{T}) where {T}
443-
handle = q.stmt.handle
444-
t = SQLite.sqlite3_column_type(handle, col)
445-
if t == SQLite.SQLITE_NULL
446-
return T()
455+
function getvalue(cursor::SQLiteCursor, column_number::Int, ::Type{Value}) where {Value}
456+
handle = cursor.statement.handle
457+
column_type = sqlite3_column_type(handle, column_number)
458+
if column_type == SQLITE_NULL
459+
Value()
447460
else
448-
TT = SQLite.juliatype(t) # native SQLite Int, Float, and Text types
449-
return SQLite.sqlitevalue(ifelse(TT === Any && !isbitstype(T), T, TT), handle, col)
461+
julia_type = juliatype(column_type) # native SQLite Int, Float, and Text types
462+
sqlitevalue(
463+
if julia_type === Any
464+
if !isbitstype(Value)
465+
Value
466+
else
467+
julia_type
468+
end
469+
else
470+
julia_type
471+
end, handle, column_number)
450472
end
451473
end
452474

453-
function Base.iterate(q::SQLiteCursor{NT}) where {NT}
454-
isdone(q) && return nothing
455-
nt = SQLite.generate_namedtuple(NT, q)
456-
q.cur_row[] = 1
457-
return nt, 1
458-
end
475+
iterate(cursor::SQLiteCursor{Row}) where {Row} =
476+
if isdone(cursor)
477+
nothing
478+
else
479+
named_tuple = generate_namedtuple(Row, cursor)
480+
cursor.cursor_row[] = 1
481+
named_tuple, 1
482+
end
459483

460-
function Base.iterate(q::SQLiteCursor{NT}, state) where {NT}
461-
state != q.cur_row[] && error("FOO")
462-
q.status[] = SQLite.sqlite3_step(q.stmt.handle)
463-
isdone(q) && return nothing
464-
nt = SQLite.generate_namedtuple(NT, q)
465-
q.cur_row[] = state + 1
466-
return nt, state + 1
467-
end
484+
iterate(cursor::SQLiteCursor{Row}, state) where {Row} =
485+
if state != cursor.cursor_row[]
486+
error("State does not match SQLiteCursor row")
487+
else
488+
cursor.status[] = sqlite3_step(cursor.statement.handle)
489+
if isdone(cursor)
490+
nothing
491+
else
492+
named_tuple = generate_namedtuple(Row, cursor)
493+
cursor.cursor_row[] = state + 1
494+
named_tuple, state + 1
495+
end
496+
end
468497

469-
IteratorInterfaceExtensions.isiterable(::OutsideCode) = true
470-
TableTraits.isiterabletable(::OutsideCode) = true
498+
isiterable(::OutsideCode) = true
499+
isiterabletable(::OutsideCode) = true
471500

472-
Base.collect(source::OutsideCode) = collect(IteratorInterfaceExtensions.getiterator(source))
501+
collect(source::OutsideCode) = collect(getiterator(source))
473502

474-
function IteratorInterfaceExtensions.getiterator(outside_code::OutsideCode)
475-
# TODO REVIEW
476-
stricttypes = true
477-
nullable = true
478-
479-
stmt = SQLite.Stmt(outside_code.outside, translate(outside_code.code))
480-
# bind!(stmt, values)
481-
status = SQLite.execute!(stmt)
482-
cols = SQLite.sqlite3_column_count(stmt.handle)
483-
header = Vector{Symbol}(undef, cols)
484-
types = Vector{Type}(undef, cols)
485-
for i = 1:cols
486-
header[i] = Symbol(unsafe_string(SQLite.sqlite3_column_name(stmt.handle, i)))
503+
second((value_1, value_2)) = value_2
504+
505+
name_and_type(handle, column_number, nullable = true, strict_types = true) =
506+
Symbol(unsafe_string(sqlite3_column_name(handle, column_number))),
507+
if strict_types
508+
julia_type = juliatype(handle, column_number)
487509
if nullable
488-
types[i] = stricttypes ? DataValue{SQLite.juliatype(stmt.handle, i)} : Any
510+
DataValue{julia_type}
489511
else
490-
types[i] = stricttypes ? SQLite.juliatype(stmt.handle, i) : Any
512+
julia_type
491513
end
514+
else
515+
Any
492516
end
493-
return SQLiteCursor{NamedTuple{Tuple(header), Tuple{types...}}}(stmt, Ref(status), Ref(0))
494-
end
495517

496-
function Base.show(io::IO, source::OutsideCode)
497-
TableShowUtils.printtable(io, IteratorInterfaceExtensions.getiterator(source), "SQLite query result")
498-
end
499-
500-
function Base.show(io::IO, ::MIME"text/html", source::OutsideCode)
501-
TableShowUtils.printHTMLtable(io, IteratorInterfaceExtensions.getiterator(source))
518+
function getiterator(outside_code::OutsideCode)
519+
# TODO REVIEW
520+
statement = Stmt(outside_code.outside, translate(outside_code.code))
521+
# bind!(statement, values)
522+
status = execute!(statement)
523+
handle = statement.handle
524+
schema = ntuple(
525+
let handle = handle
526+
column_number -> name_and_type(handle, column_number)
527+
end,
528+
sqlite3_column_count(handle)
529+
)
530+
SQLiteCursor{NamedTuple{
531+
Tuple(map_unrolled(first, schema)),
532+
Tuple{map_unrolled(second, schema)...}
533+
}}(statement, Ref(status), Ref(0))
502534
end
503535

504-
Base.Multimedia.showable(::MIME"text/html", source::OutsideCode) = true
536+
show(stream::IO, source::OutsideCode) =
537+
printtable(stream, getiterator(source), "SQLite query result")
505538

506-
function Base.show(io::IO, ::MIME"application/vnd.dataresource+json", source::OutsideCode)
507-
TableShowUtils.printdataresource(io, IteratorInterfaceExtensions.getiterator(source))
508-
end
539+
showable(::MIME"text/html", source::OutsideCode) = true
540+
show(stream::IO, ::MIME"text/html", source::OutsideCode) =
541+
printHTMLtable(stream, getiterator(source))
509542

510-
Base.Multimedia.showable(::MIME"application/vnd.dataresource+json", source::OutsideCode) = true
543+
showable(::MIME"application/vnd.dataresource+json", source::OutsideCode) = true
544+
show(stream::IO, ::MIME"application/vnd.dataresource+json", source::OutsideCode) =
545+
printdataresource(stream, getiterator(source))
511546

512547
end # module

0 commit comments

Comments
 (0)