Skip to content

Commit a9eacc8

Browse files
committed
Get tests passing
1 parent 5016353 commit a9eacc8

File tree

11 files changed

+122
-163
lines changed

11 files changed

+122
-163
lines changed

REQUIRE

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
julia 0.6
22
DataFrames 0.11
3-
Compat 0.17.0
4-
ConfParser
3+
Compat 0.40.0

src/datetime.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import Base.==
55
const MYSQL_DATE_FORMAT = Dates.DateFormat("yyyy-mm-dd")
66
const MYSQL_DATETIME_FORMAT = Dates.DateFormat("yyyy-mm-dd HH:MM:SS")
77

8+
mysql_date(str) = Dates.Date(str, MYSQL_DATE_FORMAT)
9+
mysql_datetime(str) = Dates.DateTime(contains(str, " ") ? str : "1970-01-01 " * str, MYSQL_DATETIME_FORMAT)
10+
export mysql_date, mysql_datetime
11+
812
function Base.convert(::Type{DateTime}, mtime::MYSQL_TIME)
913
if mtime.year == 0 || mtime.month == 0 || mtime.day == 0
1014
DateTime(1970, 1, 1,

src/handy.jl

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ function mysql_next_result(hndl::MySQLHandle)
7575
end
7676

7777
for func = (:mysql_field_count, :mysql_error, :mysql_insert_id)
78-
eval(quote
78+
@eval begin
7979
function ($func)(hndl::MySQLHandle, args...)
8080
hndl.mysqlptr == C_NULL && throw(MySQLInterfaceError($(string(func)) * " called with NULL connection."))
8181
return ($func)(hndl.mysqlptr, args...)
8282
end
83-
end)
83+
end
8484
end
8585

8686
"""
@@ -93,14 +93,14 @@ mysql_insert_id
9393

9494
# wrappers to take MySQLHandle as input as well as check for NULL pointer.
9595
for func = (:mysql_query, :mysql_options)
96-
eval(quote
96+
@eval begin
9797
function ($func)(hndl::MySQLHandle, args...)
9898
hndl.mysqlptr == C_NULL && throw(MySQLInterfaceError($(string(func)) * " called with NULL connection."))
9999
val = ($func)(hndl.mysqlptr, args...)
100100
val != 0 && throw(MySQLInternalError(hndl))
101101
return val
102102
end
103-
end)
103+
end
104104
end
105105

106106
"""
@@ -212,12 +212,12 @@ end
212212

213213
for func = (:mysql_stmt_num_rows, :mysql_stmt_affected_rows,
214214
:mysql_stmt_result_to_dataframe, :mysql_stmt_error)
215-
eval(quote
215+
@eval begin
216216
function ($func)(hndl::MySQLHandle, args...)
217217
hndl.stmtptr == C_NULL && throw(MySQLInterfaceError($(string(func)) * " called with NULL statement handle."))
218218
return ($func)(hndl.stmtptr, args...)
219219
end
220-
end)
220+
end
221221
end
222222

223223
"""
@@ -254,23 +254,23 @@ function mysql_stmt_bind_result(hndl::MySQLHandle, bindarr::Vector{MYSQL_BIND})
254254
end
255255

256256
for func = (:mysql_stmt_store_result, :mysql_stmt_bind_param)
257-
eval(quote
257+
@eval begin
258258
function ($func)(hndl, args...)
259259
hndl.stmtptr == C_NULL && throw(MySQLInterfaceError($(string(func)) * " called with NULL statement handle."))
260260
val = ($func)(hndl.stmtptr, args...)
261261
val != 0 && throw(MySQLStatementError(hndl))
262262
return val
263263
end
264-
end)
264+
end
265265
end
266266

267267
for func = (:mysql_num_rows, :mysql_fetch_row)
268-
eval(quote
268+
@eval begin
269269
function ($func)(hndl, args...)
270270
hndl.resptr == C_NULL && throw(MySQLInterfaceError($(string(func)) * " called with NULL result set."))
271271
return ($func)(hndl.resptr, args...)
272272
end
273-
end)
273+
end
274274
end
275275

276276
"""
@@ -279,12 +279,16 @@ Get a `MYSQL_BIND` instance given the mysql type `typ` and a `value`.
279279
mysql_bind_init(typ::MYSQL_TYPE, value) =
280280
mysql_bind_init(mysql_get_julia_type(typ), typ, value)
281281

282-
mysql_bind_init(jtype::Type{Union{Date, Missings.Missing}}, typ, value) =
283-
MYSQL_BIND([convert(MYSQL_TIME, convert(Date, value))], typ)
284-
mysql_bind_init(jtype::Type{Union{DateTime, Missings.Missing}}, typ, value) =
285-
MYSQL_BIND([convert(MYSQL_TIME, convert(DateTime, value))], typ)
282+
mysql_bind_init(jtype::Type{Date}, typ, value::Date) =
283+
MYSQL_BIND([convert(MYSQL_TIME, value)], typ)
284+
mysql_bind_init(jtype::Type{Date}, typ, value::String) =
285+
MYSQL_BIND([convert(MYSQL_TIME, mysql_date(value))], typ)
286+
mysql_bind_init(jtype::Type{DateTime}, typ, value::DateTime) =
287+
MYSQL_BIND([convert(MYSQL_TIME, value)], typ)
288+
mysql_bind_init(jtype::Type{DateTime}, typ, value::String) =
289+
MYSQL_BIND([convert(MYSQL_TIME, mysql_datetime(value))], typ)
286290

287-
mysql_bind_init(::Type{Union{String, Missings.Missing}}, typ, value) = MYSQL_BIND(value, typ)
291+
mysql_bind_init(::Type{String}, typ, value) = MYSQL_BIND(value, typ)
288292
mysql_bind_init(jtype, typ, value) = MYSQL_BIND([convert(jtype, value)], typ)
289293

290294
"""
@@ -299,7 +303,7 @@ function mysql_bind_array(typs, params)
299303
bindarr = MYSQL_BIND[]
300304
for (typ, val) in zip(typs, params)
301305
#Is the value missing or equal to `nothing`?
302-
if (isdefined(:Missings)&&(typeof(val)==Missings.Missing))||(val==nothing)
306+
if ismissing(val) || val === nothing
303307
push!(bindarr, mysql_bind_init(MYSQL_TYPE_NULL, "NULL"))
304308
else
305309
push!(bindarr, mysql_bind_init(typ, val)) #Otherwise
@@ -334,7 +338,7 @@ end
334338
Escapes a string using `mysql_real_escape_string()`, returns the escaped string.
335339
"""
336340
function mysql_escape(hndl::MySQLHandle, str::String)
337-
output = Vector{UInt8}(length(str)*2 + 1)
341+
output = Vector{UInt8}(uninitialized, length(str) * 2 + 1)
338342
output_len = mysql_real_escape_string(hndl.mysqlptr, output, str, Culong(length(str)))
339343
if output_len == typemax(Cuint)
340344
throw(MySQLInternalError(hndl))
@@ -345,9 +349,9 @@ end
345349
"""
346350
mysql_subtype(typ::DataType) -> DataType
347351
348-
Convenience function for working with missing values. If `typ` is of the form `Union{Missings.Missing, T}` it returns `T`, otherwise it returns `typ`. Not exported.
352+
Convenience function for working with missing values. If `typ` is of the form `Union{Missing, T}` it returns `T`, otherwise it returns `typ`. Not exported.
349353
"""
350-
mysql_subtype{T}(typ::Type{Union{Missings.Missing, T}})=T
354+
mysql_subtype{T}(typ::Type{Union{Missing, T}})=T
351355
mysql_subtype(typ::DataType)=typ
352356

353357
export mysql_options, mysql_connect, mysql_disconnect, mysql_execute,

src/results.jl

Lines changed: 28 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,29 @@ Given a MYSQL type get the corresponding julia type.
55
"""
66
function mysql_get_julia_type(mysqltype)
77
if (mysqltype == MYSQL_TYPE_BIT)
8-
return Union{Missings.Missing, Cuchar}
8+
return Cuchar
99

1010
elseif (mysqltype == MYSQL_TYPE_TINY ||
1111
mysqltype == MYSQL_TYPE_ENUM)
12-
return Union{Missings.Missing, Cchar}
12+
return Cchar
1313

1414
elseif (mysqltype == MYSQL_TYPE_SHORT)
15-
return Union{Missings.Missing, Cshort}
15+
return Cshort
1616

1717
elseif (mysqltype == MYSQL_TYPE_LONG ||
1818
mysqltype == MYSQL_TYPE_INT24)
19-
return Union{Missings.Missing, Cint}
19+
return Cint
2020

2121
elseif (mysqltype == MYSQL_TYPE_LONGLONG)
22-
return Union{Missings.Missing, Int64}
22+
return Int64
2323

2424
elseif (mysqltype == MYSQL_TYPE_FLOAT)
25-
return Union{Missings.Missing, Cfloat}
25+
return Cfloat
2626

2727
elseif (mysqltype == MYSQL_TYPE_DECIMAL ||
2828
mysqltype == MYSQL_TYPE_NEWDECIMAL ||
2929
mysqltype == MYSQL_TYPE_DOUBLE)
30-
return Union{Missings.Missing, Cdouble}
30+
return Cdouble
3131

3232
elseif (mysqltype == MYSQL_TYPE_NULL ||
3333
mysqltype == MYSQL_TYPE_SET ||
@@ -36,30 +36,30 @@ function mysql_get_julia_type(mysqltype)
3636
mysqltype == MYSQL_TYPE_LONG_BLOB ||
3737
mysqltype == MYSQL_TYPE_BLOB ||
3838
mysqltype == MYSQL_TYPE_GEOMETRY)
39-
return Union{Missings.Missing, String}
39+
return String
4040

4141
elseif (mysqltype == MYSQL_TYPE_YEAR)
42-
return Union{Missings.Missing, Clong}
42+
return Clong
4343

4444
elseif (mysqltype == MYSQL_TYPE_TIMESTAMP)
45-
return Union{Missings.Missing, DateTime}
45+
return DateTime
4646

4747
elseif (mysqltype == MYSQL_TYPE_DATE)
48-
return Union{Missings.Missing, Date}
48+
return Date
4949

5050
elseif (mysqltype == MYSQL_TYPE_TIME)
51-
return Union{Missings.Missing, DateTime}
51+
return DateTime
5252

5353
elseif (mysqltype == MYSQL_TYPE_DATETIME)
54-
return Union{Missings.Missing, DateTime}
54+
return DateTime
5555

5656
elseif (mysqltype == MYSQL_TYPE_VARCHAR ||
5757
mysqltype == MYSQL_TYPE_VAR_STRING ||
5858
mysqltype == MYSQL_TYPE_STRING)
59-
return Union{Missings.Missing, String}
59+
return String
6060

6161
else
62-
return Union{Missings.Missing, String}
62+
return String
6363

6464
end
6565
end
@@ -71,7 +71,7 @@ function mysql_get_ctype end
7171
mysql_get_ctype(::Type{<:Dates.TimeType}) = MYSQL_TIME
7272
mysql_get_ctype(x) = x
7373

74-
mysql_get_ctype{T}(jltype::Type{Union{Missings.Missing, T}}) = mysql_get_ctype(T)
74+
mysql_get_ctype(jltype::Type{Union{Missing, T}}) where {T} = mysql_get_ctype(T)
7575

7676
mysql_get_ctype(mysqltype::MYSQL_TYPE) =
7777
mysql_get_ctype(mysql_get_julia_type(mysqltype))
@@ -81,7 +81,7 @@ Interpret a string as a julia datatype.
8181
"""
8282
function mysql_interpret_field end
8383

84-
mysql_interpret_field{T}(strval::String, ::Type{Union{Missings.Missing, T}}) = mysql_interpret_field(strval, T)
84+
mysql_interpret_field(strval::String, ::Type{Union{Missing, T}}) where {T} = mysql_interpret_field(strval, T)
8585

8686
mysql_interpret_field(strval::String, ::Type{Cuchar}) = UInt8(strval[1])
8787

@@ -91,11 +91,8 @@ mysql_interpret_field(strval::String, ::Type{T}) where {T<:Number} =
9191
mysql_interpret_field(strval::String, ::Type{<:AbstractString}) =
9292
strval
9393

94-
mysql_interpret_field(strval::String, ::Type{Date}) =
95-
Dates.Date(datestr, MYSQL_DATE_FORMAT)
96-
97-
functionmysql_interpret_field(strval::String, ::Type{DateTime}) =
98-
Dates.DateTime(contains(strval, " ") ? strval : "1970-01-01 " * strval, MYSQL_DATETIME_FORMAT)
94+
mysql_interpret_field(strval::String, ::Type{Date}) = mysql_date(strval)
95+
mysql_interpret_field(strval::String, ::Type{DateTime}) = mysql_datetime(strval)
9996

10097
"""
10198
Load a bytestring from `result` pointer given the field index `idx`.
@@ -160,14 +157,7 @@ end
160157
"""
161158
Convert a mysql field type array to a julia type array.
162159
"""
163-
function mysql_get_jtype_array(mysqlfield_types)
164-
nfields = length(mysqlfield_types)
165-
jtypes = Array{Type}(nfields)
166-
for i = 1:nfields
167-
jtypes[i] = mysql_get_julia_type(mysqlfield_types[i])
168-
end
169-
return jtypes
170-
end
160+
mysql_get_jtype_array(mysqlfield_types) = map(x->mysql_get_julia_type(x), mysqlfield_types)
171161

172162
"""
173163
Returns true if `field` is nullable (i.e, it is not declared as `NOT NULL`)
@@ -178,40 +168,21 @@ mysql_is_nullable(field) = field.flags & NOT_NULL_FLAG == 0
178168
Get an array of boolean values indicating whether the column is
179169
declared as `NULL`(true) or `NOT NULL`(false).
180170
"""
181-
mysql_get_nullable(result) = mysql_get_nullable(mysql_metadata(result))
182-
183-
function mysql_get_nullable(meta::Array{MYSQL_FIELD})
184-
isnullable = Array{Bool}(length(meta))
185-
for i = 1:length(meta)
186-
isnullable[i] = mysql_is_nullable(meta[i])
187-
end
188-
return isnullable
189-
end
171+
mysql_get_nullable(result) = map(x->mysql_is_nullable(x), mysql_metadata(result))
190172

191173
"""
192174
Get the result as an array with each row as a vector.
193175
"""
194176
function mysql_get_result_as_array(result)
195177
nrows = mysql_num_rows(result)
196178
meta = mysql_metadata(result)
197-
retarr = Array{Array{Any}}(nrows)
198-
for i = 1:nrows
199-
retarr[i] = Array{Any}(meta.nfields)
200-
mysql_get_row_as_vector!(mysql_fetch_row(result), retarr[i],
201-
meta.jtypes, meta.is_nullables)
202-
end
203-
return retarr
179+
return [mysql_get_row_as_vector(mysql_fetch_row(result), meta.jtypes, meta.is_nullables) for i = 1:nrows]
204180
end
205181

206182
function mysql_get_result_as_tuples(result::MySQLResult)
207183
nrows = mysql_num_rows(result)
208184
meta = mysql_metadata(result)
209-
retarr = Array{Tuple}(nrows)
210-
for i = 1:nrows
211-
retarr[i] = mysql_get_row_as_tuple(mysql_fetch_row(result), meta.jtypes,
212-
meta.is_nullables)
213-
end
214-
return retarr
185+
return [mysql_get_row_as_tuple(mysql_fetch_row(result), meta.jtypes, meta.is_nullables) for i = 1:nrows]
215186
end
216187

217188
"""
@@ -275,18 +246,18 @@ function stmt_populate_row!(df, row_index, bindarr)
275246
for i = 1:length(bindarr)
276247
if bindarr[i].is_null_value != 0
277248
df[row_index, i] = missing
278-
continue
279-
end
280-
df[row_index, i] = mysql_binary_interpret_field(bindarr[i].buffer,
249+
else
250+
df[row_index, i] = mysql_binary_interpret_field(bindarr[i].buffer,
281251
convert(MYSQL_TYPE, bindarr[i].buffer_type))
252+
end
282253
end
283254
end
284255

285256
"""
286257
Get a bind array for binding to results.
287258
"""
288259
function mysql_bind_array(meta::MySQLMetadata)
289-
bindarr = Array{MYSQL_BIND}(meta.nfields)
260+
bindarr = Vector{MYSQL_BIND}(uninitialized, meta.nfields)
290261
for i in 1:meta.nfields
291262
bufflen = zero(Culong)
292263
bindbuff = C_NULL
@@ -360,7 +331,7 @@ function mysql_get_row_as_tuple(bindarr::Vector{MYSQL_BIND}, jtypes, isnullable)
360331
vec = Array{Any}(length(bindarr))
361332
for i = 1:length(bindarr)
362333
if bindarr[i].is_null_value != 0
363-
vec[i] = Missings.missing
334+
vec[i] = missing
364335
else
365336
val = mysql_binary_interpret_field(bindarr[i].buffer,
366337
convert(MYSQL_TYPE, bindarr[i].buffer_type))

src/types.jl

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,18 +159,18 @@ mutable struct MySQLResult
159159
function MySQLResult(hndl, resptr)
160160
res = new(hndl, C_NULL)
161161
res.resptr = resptr
162-
finalizer(x -> mysql_free_result(x.resptr), res)
162+
finalizer(res, x -> mysql_free_result(x.resptr))
163163
return res
164164
end
165165
end
166166

167167
"""
168168
Iterator for the mysql result.
169169
"""
170-
mutable struct MySQLRowIterator{T}
170+
mutable struct MySQLRowIterator
171171
result::MySQLResult
172-
# jtypes::Vector{Type}
173-
# is_nullables::Vector{Bool}
172+
jtypes::Vector{Type}
173+
is_nullables::Vector{Bool}
174174
rowsleft::Int64
175175
end
176176

@@ -242,9 +242,11 @@ mutable struct MySQLMetadata
242242
for i in 1:nfields
243243
names[i] = unsafe_string(fields[i].name)
244244
mtypes[i] = fields[i].field_type
245-
jtypes[i] = mysql_get_julia_type(fields[i].field_type)
245+
is_nullable = mysql_is_nullable(fields[i])
246+
is_nullables[i] = is_nullable
247+
T = mysql_get_julia_type(fields[i].field_type)
248+
jtypes[i] = is_nullable ? Union{Missing, T} : T
246249
lens[i] = fields[i].field_length
247-
is_nullables[i] = mysql_is_nullable(fields[i])
248250
end
249251
new(names, mtypes, jtypes, lens, is_nullables, nfields)
250252
end

test/REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ConfParser

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ conf = ConfParse("server.ini")
66
parse_conf!(conf)
77

88
const HOST = retrieve(conf, "default", "host") |> parse
9+
const PORT = retrieve(conf, "default", "port") |> parse
910
const USER = retrieve(conf, "default", "user") |> parse
1011
const PASS = retrieve(conf, "default", "pass") |> parse
1112

test/server.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
;; have database creation and user creation privilege.
33
[default]
44
host="127.0.0.1"
5+
port="3306"
56
user="root"
67
pass="" ; In Travis CI the root password is an empty string.

0 commit comments

Comments
 (0)