@@ -4,13 +4,15 @@ import Base: !, &, |, ==, !=, coalesce, getproperty, in, isequal, isless, ismiss
44using Base: Generator, NamedTuple, tail
55import Base. Iterators: drop, take
66using Base. Meta: quot
7- import DataFrames: DataFrame
87import MacroTools
98using MacroTools: @capture
109import QueryOperators
1110import QueryOperators: orderby, query
1211import SQLite
1312using SQLite: columns, DB, tables
13+ import IteratorInterfaceExtensions, TableTraits
14+ using DataValues
15+ import TableShowUtils
1416
1517map_unrolled (call, variables:: Tuple{} ) = ()
1618map_unrolled (call, variables) =
@@ -56,14 +58,6 @@ get_column_names(outside::DB, table_name) =
5658 as_symbols (columns (outside, String (table_name)). name)
5759export get_column_names
5860
59- """
60- submit_to(outside, text)
61-
62- Send `text` to `outside`
63- """
64- submit_to (outside:: DB , text) = DataFrame (Query (outside, text))
65- export submit_to
66-
6761"""
6862 abstract type OutsideTables{Outside} end
6963
@@ -398,14 +392,11 @@ translate_call(::typeof(take), iterator, number) =
398392
399393# SQLite interface
400394
401- using DataFrames: DataFrame
402-
403395to_symbols (them) = map_unrolled (Symbol, (them... ,))
404396
405397get_table_names (database:: DB ) = to_symbols (tables (database). name)
406398get_column_names (database:: DB , table_name) =
407399 to_symbols (SQLite. columns (database, String (table_name)). name)
408- submit_to (database:: DB , text) = DataFrame (SQLite. Query (database, text))
409400
410401# dispatch
411402
@@ -440,10 +431,92 @@ translate(code::Expr) =
440431# collect
441432query (outside_code:: OutsideCode ) = outside_code
442433
443- DataFrame (outside_code:: OutsideCode ) =
444- submit_to (
445- outside_code. outside,
446- translate (outside_code. code)
447- )
434+ struct SQLiteCursor{T}
435+ stmt:: SQLite.Stmt
436+ status:: Base.RefValue{Cint}
437+ cur_row:: Base.RefValue{Int}
438+ end
439+
440+ Base. eltype (q:: SQLiteCursor{T} ) where {T} = T
441+ Base. IteratorSize (:: Type{<:SQLiteCursor} ) = Base. SizeUnknown ()
442+
443+ function isdone (q:: SQLiteCursor )
444+ st = q. status[]
445+ st == SQLite. SQLITE_DONE && return true
446+ st == SQLite. SQLITE_ROW || SQLite. sqliteerror (q. stmt. db)
447+ return false
448+ end
449+
450+ function SQLite. getvalue (q:: SQLiteCursor , col:: Int , :: Type{T} ) where {T}
451+ handle = q. stmt. handle
452+ t = SQLite. sqlite3_column_type (handle, col)
453+ if t == SQLite. SQLITE_NULL
454+ return T ()
455+ else
456+ TT = SQLite. juliatype (t) # native SQLite Int, Float, and Text types
457+ return SQLite. sqlitevalue (ifelse (TT === Any && ! isbitstype (T), T, TT), handle, col)
458+ end
459+ end
460+
461+
462+
463+ function Base. iterate (q:: SQLiteCursor{NT} ) where {NT}
464+ isdone (q) && return nothing
465+ nt = SQLite. generate_namedtuple (NT, q)
466+ q. cur_row[] = 1
467+ return nt, 1
468+ end
469+
470+ function Base. iterate (q:: SQLiteCursor{NT} , state) where {NT}
471+ state != q. cur_row[] && error (" FOO" )
472+ q. status[] = SQLite. sqlite3_step (q. stmt. handle)
473+ isdone (q) && return nothing
474+ nt = SQLite. generate_namedtuple (NT, q)
475+ q. cur_row[] = state + 1
476+ return nt, state + 1
477+ end
478+
479+ IteratorInterfaceExtensions. isiterable (:: OutsideCode ) = true
480+ TableTraits. isiterabletable (:: OutsideCode ) = true
481+
482+ Base. collect (source:: OutsideCode ) = collect (IteratorInterfaceExtensions. getiterator (source))
483+
484+ function IteratorInterfaceExtensions. getiterator (outside_code:: OutsideCode )
485+ # TODO REVIEW
486+ stricttypes = true
487+ nullable = true
488+
489+ stmt = SQLite. Stmt (outside_code. outside, translate (outside_code. code))
490+ # bind!(stmt, values)
491+ status = SQLite. execute! (stmt)
492+ cols = SQLite. sqlite3_column_count (stmt. handle)
493+ header = Vector {Symbol} (undef, cols)
494+ types = Vector {Type} (undef, cols)
495+ for i = 1 : cols
496+ header[i] = Symbol (unsafe_string (SQLite. sqlite3_column_name (stmt. handle, i)))
497+ if nullable
498+ types[i] = stricttypes ? DataValue{SQLite. juliatype (stmt. handle, i)} : Any
499+ else
500+ types[i] = stricttypes ? SQLite. juliatype (stmt. handle, i) : Any
501+ end
502+ end
503+ return SQLiteCursor {NamedTuple{Tuple(header), Tuple{types...}}} (stmt, Ref (status), Ref (0 ))
504+ end
505+
506+ function Base. show (io:: IO , source:: OutsideCode )
507+ TableShowUtils. printtable (io, IteratorInterfaceExtensions. getiterator (source), " SQLite query result" )
508+ end
509+
510+ function Base. show (io:: IO , :: MIME"text/html" , source:: OutsideCode )
511+ TableShowUtils. printHTMLtable (io, IteratorInterfaceExtensions. getiterator (source))
512+ end
513+
514+ Base. Multimedia. showable (:: MIME"text/html" , source:: OutsideCode ) = true
515+
516+ function Base. show (io:: IO , :: MIME"application/vnd.dataresource+json" , source:: OutsideCode )
517+ TableShowUtils. printdataresource (io, IteratorInterfaceExtensions. getiterator (source))
518+ end
519+
520+ Base. Multimedia. showable (:: MIME"application/vnd.dataresource+json" , source:: OutsideCode ) = true
448521
449522end # module
0 commit comments