Skip to content

Commit

Permalink
Ensure passwords can be read from options files (#180)
Browse files Browse the repository at this point in the history
Fixes #166. Wowza what an issue. After spending way too much time
googling various forms of "can't read password from mariadb options
file", I started poking around the capi.jl file, and reading anything
related to "options". I was trying to see if there was a way to have a
debug print of what options were actually read from an options file.
That's when I found the following in the docs for `mysql_real_connect`,
which I'm now very thankful that past me decided to copy/paste all the
api docs for every single api function.

```
For passwd, specify a value of NULL. (For the password, a value of the empty string in the mysql_real_connect() call cannot be overridden in an option file, because the empty string indicates explicitly that the MySQL account must have an empty password.)
```

So if you want a password to be read from an option file, you need to
pass NULL to the `mysql_real_connect` function; but we were always
passing an empty string! So it prevented reading any password from
option files. Anyway, the fix is just that: by default we'll pass
`nothing` as the password, which will pass NULL to the actual api call,
allowing passwords to be read from option files.
  • Loading branch information
quinnj authored Mar 10, 2021
1 parent ce1f9fc commit 4cd7424
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/MySQL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mutable struct Connection <: DBInterface.Connection
db::String
lastexecute::Any

function Connection(host::String, user::String, passwd::String, db::String, port::Integer, unix_socket::String; kw...)
function Connection(host::String, user::String, passwd::Union{String, Nothing}, db::String, port::Integer, unix_socket::String; kw...)
mysql = API.init()
API.setoption(mysql, API.MYSQL_PLUGIN_DIR, API.PLUGIN_DIR)
API.setoption(mysql, API.MYSQL_SET_CHARSET_NAME, "utf8mb4")
Expand Down Expand Up @@ -285,7 +285,7 @@ Connect to a MySQL database with provided `host`, `user`, and `passwd` positiona
* `read_default_group::Bool`: only the default option groups are read from specified option file(s)
* `option_group::String`: it is interpreted as a custom option group, and that custom option group is read in addition to the default option groups.
"""
DBInterface.connect(::Type{Connection}, host::String, user::String, passwd::String; db::String="", port::Integer=3306, unix_socket::String=API.MYSQL_DEFAULT_SOCKET, kw...) =
DBInterface.connect(::Type{Connection}, host::String, user::String, passwd::Union{String, Nothing}=nothing; db::String="", port::Integer=3306, unix_socket::String=API.MYSQL_DEFAULT_SOCKET, kw...) =
Connection(host, user, passwd, db, port, unix_socket; kw...)

"""
Expand Down
4 changes: 2 additions & 2 deletions src/api/capi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1129,8 +1129,8 @@ If no value is found in an option file for a parameter, its default value is use
Return Values
A MYSQL* connection handler if the connection was successful, NULL if the connection was unsuccessful. For a successful connection, the return value is the same as the value of the first parameter.
"""=#
function connect(mysql::MYSQL, host::String, user::String, passwd::String, db::String, port::Integer, unix_socket::String, client_flag)
@checknull mysql mysql_real_connect(mysql.ptr, host, user, passwd, db, port, unix_socket, client_flag)
function connect(mysql::MYSQL, host::String, user::String, passwd::Union{String, Nothing}, db::String, port::Integer, unix_socket::String, client_flag)
@checknull mysql mysql_real_connect(mysql.ptr, host, user, passwd === nothing ? Ptr{UInt8}(C_NULL) : passwd, db, port, unix_socket, client_flag)
return mysql
end

Expand Down
3 changes: 2 additions & 1 deletion test/my.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ host=127.0.0.1
user=root
port=3306
connect_timeout=30
report-data-truncation=true
report-data-truncation=true
password = ""
4 changes: 2 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ conn = DBInterface.connect(MySQL.Connection, "127.0.0.1", "root", ""; port=3306)
DBInterface.close!(conn)

# https://github.com/JuliaDatabases/MySQL.jl/issues/170
conn = DBInterface.connect(MySQL.Connection, "mysql://127.0.0.1", "root", ""; port=3306)
conn = DBInterface.connect(MySQL.Connection, "mysql://127.0.0.1", "root"; port=3306)
DBInterface.close!(conn)

# load host/user + options from file
conn = DBInterface.connect(MySQL.Connection, "", "", ""; option_file="my.ini")
conn = DBInterface.connect(MySQL.Connection, "", ""; option_file=joinpath(dirname(pathof(MySQL)), "../test/", "my.ini"))
@test isopen(conn)

DBInterface.execute(conn, "DROP DATABASE if exists mysqltest")
Expand Down

0 comments on commit 4cd7424

Please sign in to comment.