Skip to content

Commit 301a345

Browse files
authored
Jq/overhaul2 (#94)
* Overhaul the package to modernize the API, provide better type conversion support, and fix several outstanding issues. Also ensures CI-testing works for OSX.
1 parent 5fa2ad2 commit 301a345

17 files changed

+712
-1077
lines changed

.travis.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
# Documentation: http://docs.travis-ci.com/user/languages/julia/
22
language: julia
3+
34
services:
45
- mysql
6+
57
os:
68
- linux
79
- osx
10+
811
julia:
912
- 0.6
1013
- nightly
14+
1115
notifications:
1216
email: false
13-
# uncomment the following lines to override the default test script
14-
#script:
15-
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
16-
# - julia -e 'Pkg.clone(pwd()); Pkg.build("MySQL"); Pkg.test("MySQL"; coverage=true)'
17+
1718
after_success:
1819
# push coverage results to Coveralls
1920
- julia -e 'cd(Pkg.dir("MySQL")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
@@ -22,6 +23,9 @@ after_success:
2223
before_script:
2324
- export OLD_PATH=$LD_LIBRARY_PATH
2425
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`mysql_config --libs | cut -d ' ' -f1 | sed 's/-L//'`
26+
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install mysql ; fi
27+
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mysql.server start ; fi
28+
2529
after_script:
2630
- export LD_LIBRARY_PATH=$OLD_PATH
2731
- unset OLD_PATH

REQUIRE

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
julia 0.6
2-
DataFrames 0.11
2+
DataStreams
33
Compat 0.39.0
4+
Missings
5+
DecFP

src/MySQL.jl

Lines changed: 126 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,129 @@
11
__precompile__(true)
22
module MySQL
3-
using Compat
4-
using DataFrames
5-
using Missings
6-
using Compat.Dates
7-
8-
include("config.jl")
9-
include("consts.jl")
10-
include("types.jl")
11-
include("datetime.jl")
12-
include("api.jl")
13-
include("results.jl")
14-
include("iterators.jl")
15-
include("handy.jl")
3+
using Compat, Compat.Dates
4+
using DataStreams, Missings
5+
6+
export Data
7+
8+
@static if isdefined(Core, :NamedTuple)
9+
macro NT(args...)
10+
return esc(:(($(args...),)))
11+
end
12+
else
13+
using NamedTuples
1614
end
15+
16+
abstract type MySQLError end
17+
# For errors that happen in MySQL.jl
18+
mutable struct MySQLInterfaceError <: MySQLError
19+
msg::String
20+
end
21+
Base.showerror(io::IO, e::MySQLInterfaceError) = print(io, e.msg)
22+
23+
include("api.jl")
24+
using .API
25+
26+
include("types.jl")
27+
28+
function setoptions!(ptr, opts)
29+
ptr == C_NULL && throw(MySQLInterfaceError("`MySQL.setoptions!` called with NULL connection."))
30+
for (k, v) in opts
31+
val = API.mysql_options(ptr, k, v)
32+
val != 0 && throw(MySQLInternalError(ptr))
33+
end
34+
nothing
35+
end
36+
37+
"""
38+
MySQL.connect(host::String, user::String, passwd::String; db::String = "", port = "3306", socket::String = MySQL.API.MYSQL_DEFAULT_SOCKET, opts = Dict())
39+
40+
Connect to a MySQL database.
41+
"""
42+
function connect(host::String, user::String, passwd::String; db::String="", port::Integer=3306, unix_socket::String=API.MYSQL_DEFAULT_SOCKET, client_flag=API.CLIENT_MULTI_STATEMENTS, opts = Dict())
43+
_ptr = C_NULL
44+
_ptr = API.mysql_init(_ptr)
45+
_ptr == C_NULL && throw(MySQLInterfaceError("Failed to initialize MySQL database"))
46+
setoptions!(_ptr, opts)
47+
ptr = API.mysql_real_connect(_ptr, host, user, passwd,
48+
db, UInt32(port), unix_socket, client_flag)
49+
ptr == C_NULL && throw(MySQLInternalError(_ptr))
50+
return Connection(ptr, host, string(port), user, db)
51+
end
52+
53+
"""
54+
MySQL.disconnect(conn::MySQL.Connection)
55+
56+
Close a handle to a MySQL database opened by `MySQL.connect`.
57+
"""
58+
function disconnect(conn::Connection)
59+
conn.ptr == C_NULL && throw(MySQLInterfaceError("Method called with NULL connection."))
60+
API.mysql_close(conn.ptr)
61+
conn.ptr = C_NULL
62+
conn.host = ""
63+
conn.user = ""
64+
conn.db = ""
65+
return nothing
66+
end
67+
68+
function insertid(conn::Connection)
69+
conn.ptr == C_NULL && throw(MySQLInterfaceError("MySQL.insertid called with NULL connection."))
70+
return API.mysql_insert_id(conn.ptr)
71+
end
72+
73+
"""
74+
MySQL.escape(conn::MySQL.Connection, str::String) -> String
75+
76+
Escapes a string using `mysql_real_escape_string()`, returns the escaped string.
77+
"""
78+
function escape(conn::MySQL.Connection, str::String)
79+
output = Vector{UInt8}(uninitialized, length(str) * 2 + 1)
80+
output_len = API.mysql_real_escape_string(conn.ptr, output, str, Culong(length(str)))
81+
if output_len == typemax(Cuint)
82+
throw(MySQLInternalError(conn))
83+
end
84+
return String(output[1:output_len])
85+
end
86+
87+
"""
88+
MySQL.execute!(conn, sql) => Void
89+
90+
execute an sql statement without returning results (useful for DDL statements, update, delete, etc.)
91+
"""
92+
function execute!(conn::Connection, sql::String)
93+
conn.ptr == C_NULL && throw(MySQLInterfaceError("`MySQL.execute!` called with NULL connection."))
94+
API.mysql_query(conn.ptr, sql) == 0 || throw(MySQLInternalError(conn))
95+
return API.mysql_affected_rows(conn.ptr)
96+
end
97+
98+
"""
99+
MySQL.query(conn, sql, sink=Data.Table; append::Bool=false) => sink
100+
101+
execute an sql statement and return the results in `sink`, which can be any valid `Data.Sink` (interface from DataStreams.jl). By default, a NamedTuple of Vectors are returned.
102+
103+
Passing `append=true` as a keyword argument will cause the resultset to be _appended_ to the sink instead of replacing.
104+
"""
105+
function query end
106+
107+
function query(conn::Connection, sql::String, sink::Type=Data.Table, args...; append::Bool=false, kwargs...)
108+
source = Query(conn, sql; kwargs...)
109+
sink = Data.stream!(source, sink, args...; append=append)
110+
return Data.close!(sink)
111+
end
112+
113+
function query(conn::Connection, sql::String, sink::T; append::Bool=false, kwargs...) where {T}
114+
source = Query(conn, sql; kwargs...)
115+
sink = Data.stream!(source, sink; append=append)
116+
return Data.close!(sink)
117+
end
118+
119+
query(source::Query, sink=Data.Table, args...; append::Bool=false, transforms::Dict=Dict{Int,Function}()) = (sink = Data.stream!(source, sink, args...; append=append, transforms=transforms); return Data.close!(sink))
120+
query(source::Query, sink::T; append::Bool=false, transforms::Dict=Dict{Int,Function}()) where {T} = (sink = Data.stream!(source, sink; append=append, transforms=transforms); return Data.close!(sink))
121+
122+
include("prepared.jl")
123+
124+
Base.@deprecate mysql_options MySQL.setoptions!
125+
Base.@deprecate mysql_connect MySQL.connect
126+
Base.@deprecate mysql_disconnect MySQL.disconnect
127+
Base.@deprecate mysql_insert_id MySQL.insertid
128+
129+
end # module

0 commit comments

Comments
 (0)