Skip to content

Commit 1391380

Browse files
committed
Switch from DataStreams to Tables
1 parent 3e1c456 commit 1391380

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

src/tables.jl

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using Tables
2+
3+
const column_types = Dict(
4+
JDBC_COLTYPE_ARRAY=>Array,
5+
JDBC_COLTYPE_BIGINT=>Int64,
6+
JDBC_COLTYPE_BIT=>Bool,
7+
JDBC_COLTYPE_BOOLEAN=>Bool,
8+
JDBC_COLTYPE_CHAR=>String,
9+
JDBC_COLTYPE_DATE=>Date,
10+
JDBC_COLTYPE_DECIMAL=>Float64,
11+
JDBC_COLTYPE_DOUBLE=>Float64,
12+
JDBC_COLTYPE_FLOAT=>Float32,
13+
JDBC_COLTYPE_INTEGER=>Int32,
14+
JDBC_COLTYPE_LONGNVARCHAR=>String,
15+
JDBC_COLTYPE_LONGVARCHAR=>String,
16+
JDBC_COLTYPE_NCHAR=>String,
17+
JDBC_COLTYPE_NUMERIC=>Float64,
18+
JDBC_COLTYPE_NVARCHAR=>String,
19+
JDBC_COLTYPE_REAL=>Float64,
20+
JDBC_COLTYPE_ROWID=>Int64,
21+
JDBC_COLTYPE_SMALLINT=>Int16,
22+
JDBC_COLTYPE_TIME=>DateTime,
23+
JDBC_COLTYPE_TIMESTAMP=>DateTime,
24+
JDBC_COLTYPE_TINYINT=>Int8,
25+
JDBC_COLTYPE_VARCHAR=>String
26+
)
27+
28+
29+
usedriver(str::AbstractString) = JavaCall.addClassPath(str)
30+
31+
32+
struct Source
33+
rs::JResultSet
34+
md::JResultSetMetaData
35+
end
36+
Source(rs::JResultSet) = Source(rs, getMetaData(rs))
37+
Source(stmt::JStatement, query::AbstractString) = Source(executeQuery(stmt, query))
38+
Source(rowit::JDBCRowIterator) = Source(rowit.rs)
39+
function Source(csr::Cursor)
40+
if csr.rs == nothing
41+
throw(ArgumentError("A cursor must contain a valid JResultSet to construct a Source."))
42+
else
43+
Source(csr.rs)
44+
end
45+
end
46+
47+
# these methods directly access the underlying JResultSet and are used in Schema constructor
48+
function coltype(s::Source, col::Int)
49+
dtype = get(column_types, getColumnType(s.md, col), Any)
50+
if isNullable(s.md, col) == COLUMN_NO_NULLS
51+
dtype
52+
else
53+
Union{dtype, Missing}
54+
end
55+
end
56+
colname(s::Source, col::Int) = getColumnName(s.md, col)
57+
ncols(s::Source) = getColumnCount(s.md)
58+
59+
coltypes(s::Source) = Type[coltype(s, i) for i 1:ncols(s)]
60+
colnames(s::Source) = Symbol[colname(s, i) for i 1:ncols(s)]
61+
62+
Tables.istable(::Type{<:Source}) = true
63+
Tables.rowaccess(::Type{<:Source}) = true
64+
Tables.rows(s::Source) = s
65+
Tables.schema(s::Source) = Tables.Schema(colnames(s), coltypes(s))
66+
67+
Base.IteratorSize(::Type{<:Source}) = Base.SizeUnknown()
68+
Base.eltype(s::Source) = namedtupletype(Tables.schema(s))
69+
namedtupletype(::Tables.Schema{names, types}) where {names, types} = NamedTuple{names, types}
70+
71+
# TODO currently jdbc_get_method is very inefficient
72+
pullfield(s::Source, col::Int) = jdbc_get_method(getColumnType(s.md, col))(s.rs, col)
73+
74+
jdbcconvert(::Type{T}, s, x) where {T} = convert(T, x)
75+
jdbcconvert(::Type{Union{T, Missing}}, s, x) where {T} = wasNull(s.rs) ? missing : convert(T, x)
76+
77+
function Base.iterate(s::Source, NT::NamedTuple{names, types}=namedtupletype(s)) where {names, types}
78+
isdone(s.rs) && return nothing
79+
return NT(convert(fieldtype(types, i), s, pullfield(s, i)) for i = 1:fieldcount(types)), NT
80+
end
81+
82+
load(::Type{T}, s::Source) where {T} = Data.close!(Data.stream!(s, T))
83+
load(::Type{T}, s::Source) where {T} = Tables.materializer(T)(s)
84+
load(::Type{T}, rs::JResultSet) where {T} = load(T, Source(rs))
85+
load(::Type{T}, stmt::JStatement, query::AbstractString) where {T} = load(T, Source(stmt, query))
86+
load(::Type{T}, csr::Union{JDBC.Cursor,JDBCRowIterator}) where {T} = load(T, Source(csr))
87+
function load(::Type{T}, csr::Cursor, q::AbstractString) where T
88+
execute!(csr, q)
89+
load(T, csr)
90+
end
91+

0 commit comments

Comments
 (0)