Skip to content

Commit

Permalink
allow AbstractString in various interfaces (#190)
Browse files Browse the repository at this point in the history
In particular, an AbstractString value can now be used as

- a connection parameter or an option value;
- a SQL statement;
- an input parameter;
- a string literal to escape.
  • Loading branch information
xitology authored Apr 12, 2022
1 parent c514ff6 commit 8a05d1c
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 60 deletions.
84 changes: 42 additions & 42 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::Union{String, Nothing}, db::String, port::Integer, unix_socket::String; kw...)
function Connection(host::AbstractString, user::AbstractString, passwd::Union{AbstractString, Nothing}, db::AbstractString, port::Integer, unix_socket::AbstractString; 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 @@ -105,38 +105,38 @@ function clientflags(;
end

function setoptions!(mysql;
init_command::Union{String, Nothing}=nothing,
init_command::Union{AbstractString, Nothing}=nothing,
connect_timeout::Union{Integer, Nothing}=nothing,
reconnect::Union{Bool, Nothing}=nothing,
read_timeout::Union{Integer, Nothing}=nothing,
write_timeout::Union{Integer, Nothing}=nothing,
data_truncation::Union{Bool, Nothing}=nothing,
charset_dir::Union{String, Nothing}=nothing,
charset_name::Union{String, Nothing}=nothing,
bind::Union{String, Nothing}=nothing,
charset_dir::Union{AbstractString, Nothing}=nothing,
charset_name::Union{AbstractString, Nothing}=nothing,
bind::Union{AbstractString, Nothing}=nothing,
max_allowed_packet::Union{Integer, Nothing}=nothing,
net_buffer_length::Union{Integer, Nothing}=nothing,
named_pipe::Union{Bool, Nothing}=nothing,
protocol::Union{API.mysql_protocol_type, Nothing}=nothing,
ssl_key::Union{String, Nothing}=nothing,
ssl_cert::Union{String, Nothing}=nothing,
ssl_ca::Union{String, Nothing}=nothing,
ssl_capath::Union{String, Nothing}=nothing,
ssl_cipher::Union{String, Nothing}=nothing,
ssl_crl::Union{String, Nothing}=nothing,
ssl_crlpath::Union{String, Nothing}=nothing,
passphrase::Union{String, Nothing}=nothing,
ssl_key::Union{AbstractString, Nothing}=nothing,
ssl_cert::Union{AbstractString, Nothing}=nothing,
ssl_ca::Union{AbstractString, Nothing}=nothing,
ssl_capath::Union{AbstractString, Nothing}=nothing,
ssl_cipher::Union{AbstractString, Nothing}=nothing,
ssl_crl::Union{AbstractString, Nothing}=nothing,
ssl_crlpath::Union{AbstractString, Nothing}=nothing,
passphrase::Union{AbstractString, Nothing}=nothing,
ssl_verify_server_cert::Union{Bool, Nothing}=nothing,
ssl_enforce::Union{Bool, Nothing}=nothing,
default_auth::Union{String, Nothing}=nothing,
connection_handler::Union{String, Nothing}=nothing,
plugin_dir::Union{String, Nothing}=nothing,
default_auth::Union{AbstractString, Nothing}=nothing,
connection_handler::Union{AbstractString, Nothing}=nothing,
plugin_dir::Union{AbstractString, Nothing}=nothing,
secure_auth::Union{Bool, Nothing}=nothing,
server_public_key::Union{String, Nothing}=nothing,
server_public_key::Union{AbstractString, Nothing}=nothing,
read_default_file::Union{Bool, Nothing}=nothing,
option_file::Union{String, Nothing}=nothing,
option_file::Union{AbstractString, Nothing}=nothing,
read_default_group::Union{Bool, Nothing}=nothing,
option_group::Union{String, Nothing}=nothing,
option_group::Union{AbstractString, Nothing}=nothing,
kw...
)
if init_command !== nothing
Expand Down Expand Up @@ -239,12 +239,12 @@ function setoptions!(mysql;
end

"""
DBInterface.connect(MySQL.Connection, 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())
DBInterface.connect(MySQL.Connection, host::AbstractString, user::AbstractString, passwd::AbstractString; db::AbstractString="", port::Integer=3306, unix_socket::AbstractString=API.MYSQL_DEFAULT_SOCKET, client_flag=API.CLIENT_MULTI_STATEMENTS, opts = Dict())
Connect to a MySQL database with provided `host`, `user`, and `passwd` positional arguments. Supported keyword arguments include:
* `db::String=""`: attach to a database by default
* `db::AbstractString=""`: attach to a database by default
* `port::Integer=3306`: connect to the database on a specific port
* `unix_socket::String`: specifies the socket or named pipe that should be used
* `unix_socket::AbstractString`: specifies the socket or named pipe that should be used
* `found_rows::Bool=false`: Return the number of matched rows instead of number of changed rows
* `no_schema::Bool=false`: Forbids the use of database.tablename.column syntax and forces the SQL parser to generate an error.
* `compress::Bool=false`: Use compression protocol
Expand All @@ -258,34 +258,34 @@ Connect to a MySQL database with provided `host`, `user`, and `passwd` positiona
* `read_timeout::Integer`: Specifies the timeout in seconds for reading packets from the server.
* `write_timeout::Integer`: Specifies the timeout in seconds for reading packets from the server.
* `data_truncation::Bool`: Enable or disable reporting data truncation errors for prepared statements
* `charset_dir::String`: character set files directory
* `charset_name::String`: Specify the default character set for the connection
* `bind::String`: Specify the network interface from which to connect to the database, like `"192.168.8.3"`
* `charset_dir::AbstractString`: character set files directory
* `charset_name::AbstractString`: Specify the default character set for the connection
* `bind::AbstractString`: Specify the network interface from which to connect to the database, like `"192.168.8.3"`
* `max_allowed_packet::Integer`: The maximum packet length to send to or receive from server. The default is 16MB, the maximum 1GB.
* `net_buffer_length::Integer`: The buffer size for TCP/IP and socket communication. Default is 16KB.
* `named_pipe::Bool`: For Windows operating systems only: Use named pipes for client/server communication.
* `protocol::MySQL.API.mysql_protocol_type`: Specify the type of client/server protocol. Possible values are: `MySQL.API.MYSQL_PROTOCOL_TCP`, `MySQL.API.MYSQL_PROTOCOL_SOCKET`, `MySQL.API.MYSQL_PROTOCOL_PIPE`, `MySQL.API.MYSQL_PROTOCOL_MEMORY`.
* `ssl_key::String`: Defines a path to a private key file to use for TLS. This option requires that you use the absolute path, not a relative path. If the key is protected with a passphrase, the passphrase needs to be specified with `passphrase` keyword argument.
* `passphrase::String`: Specify a passphrase for a passphrase-protected private key, as configured by the `ssl_key` keyword argument.
* `ssl_cert::String`: Defines a path to the X509 certificate file to use for TLS. This option requires that you use the absolute path, not a relative path.
* `ssl_ca::String`: Defines a path to a PEM file that should contain one or more X509 certificates for trusted Certificate Authorities (CAs) to use for TLS. This option requires that you use the absolute path, not a relative path.
* `ssl_capath::String`: Defines a path to a directory that contains one or more PEM files that should each contain one X509 certificate for a trusted Certificate Authority (CA) to use for TLS. This option requires that you use the absolute path, not a relative path. The directory specified by this option needs to be run through the openssl rehash command.
* `ssl_cipher::String`: Defines a list of permitted ciphers or cipher suites to use for TLS, like `"DHE-RSA-AES256-SHA"`
* `ssl_crl::String`: Defines a path to a PEM file that should contain one or more revoked X509 certificates to use for TLS. This option requires that you use the absolute path, not a relative path.
* `ssl_crlpath::String`: Defines a path to a directory that contains one or more PEM files that should each contain one revoked X509 certificate to use for TLS. This option requires that you use the absolute path, not a relative path. The directory specified by this option needs to be run through the openssl rehash command.
* `ssl_key::AbstractString`: Defines a path to a private key file to use for TLS. This option requires that you use the absolute path, not a relative path. If the key is protected with a passphrase, the passphrase needs to be specified with `passphrase` keyword argument.
* `passphrase::AbstractString`: Specify a passphrase for a passphrase-protected private key, as configured by the `ssl_key` keyword argument.
* `ssl_cert::AbstractString`: Defines a path to the X509 certificate file to use for TLS. This option requires that you use the absolute path, not a relative path.
* `ssl_ca::AbstractString`: Defines a path to a PEM file that should contain one or more X509 certificates for trusted Certificate Authorities (CAs) to use for TLS. This option requires that you use the absolute path, not a relative path.
* `ssl_capath::AbstractString`: Defines a path to a directory that contains one or more PEM files that should each contain one X509 certificate for a trusted Certificate Authority (CA) to use for TLS. This option requires that you use the absolute path, not a relative path. The directory specified by this option needs to be run through the openssl rehash command.
* `ssl_cipher::AbstractString`: Defines a list of permitted ciphers or cipher suites to use for TLS, like `"DHE-RSA-AES256-SHA"`
* `ssl_crl::AbstractString`: Defines a path to a PEM file that should contain one or more revoked X509 certificates to use for TLS. This option requires that you use the absolute path, not a relative path.
* `ssl_crlpath::AbstractString`: Defines a path to a directory that contains one or more PEM files that should each contain one revoked X509 certificate to use for TLS. This option requires that you use the absolute path, not a relative path. The directory specified by this option needs to be run through the openssl rehash command.
* `ssl_verify_server_cert::Bool`: Enables (or disables) server certificate verification.
* `ssl_enforce::Bool`: Whether to force TLS
* `default_auth::String`: Default authentication client-side plugin to use.
* `connection_handler::String`: Specify the name of a connection handler plugin.
* `plugin_dir::String`: Specify the location of client plugins. The plugin directory can also be specified with the MARIADB_PLUGIN_DIR environment variable.
* `default_auth::AbstractString`: Default authentication client-side plugin to use.
* `connection_handler::AbstractString`: Specify the name of a connection handler plugin.
* `plugin_dir::AbstractString`: Specify the location of client plugins. The plugin directory can also be specified with the MARIADB_PLUGIN_DIR environment variable.
* `secure_auth::Bool`: Refuse to connect to the server if the server uses the mysql_old_password authentication plugin. This mode is off by default, which is a difference in behavior compared to MySQL 5.6 and later, where it is on by default.
* `server_public_key::String`: Specifies the name of the file which contains the RSA public key of the database server. The format of this file must be in PEM format. This option is used by the caching_sha2_password client authentication plugin.
* `server_public_key::AbstractString`: Specifies the name of the file which contains the RSA public key of the database server. The format of this file must be in PEM format. This option is used by the caching_sha2_password client authentication plugin.
* `read_default_file::Bool`: only the default option files are read
* `option_file::String`: the argument is interpreted as a path to a custom option file, and only that option file is read.
* `option_file::AbstractString`: the argument is interpreted as a path to a custom option file, and only that option file is read.
* `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.
* `option_group::AbstractString`: 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::Union{String, Nothing}=nothing; db::String="", port::Integer=3306, unix_socket::String=API.MYSQL_DEFAULT_SOCKET, kw...) =
DBInterface.connect(::Type{Connection}, host::AbstractString, user::AbstractString, passwd::Union{AbstractString, Nothing}=nothing; db::AbstractString="", port::Integer=3306, unix_socket::AbstractString=API.MYSQL_DEFAULT_SOCKET, kw...) =
Connection(host, user, passwd, db, port, unix_socket; kw...)

"""
Expand Down Expand Up @@ -317,10 +317,10 @@ include("prepare.jl")
include("load.jl")

"""
MySQL.escape(conn::MySQL.Connection, str::String) -> String
MySQL.escape(conn::MySQL.Connection, str::AbstractString) -> String
Escapes a string using `mysql_real_escape_string()`, returns the escaped string.
"""
escape(conn::Connection, sql::String) = API.escapestring(conn.mysql, sql)
escape(conn::Connection, sql::AbstractString) = API.escapestring(conn.mysql, sql)

end # module
20 changes: 10 additions & 10 deletions src/api/capi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ER_WRONG_DB_NAME
The database name was too long.
"""=#
function changeuser(mysql::MYSQL, user::String, password::String, db::String)
function changeuser(mysql::MYSQL, user::AbstractString, password::AbstractString, db::AbstractString)
return @checksuccess mysql mysql_change_user(mysql.ptr, user, password, isempty(db) ? C_NULL : db)
end

Expand Down Expand Up @@ -137,7 +137,7 @@ name: The plugin name.
type: The plugin type.
"""=#
function findplugin(mysql::MYSQL, name::String, type::Integer)
function findplugin(mysql::MYSQL, name::AbstractString, type::Integer)
return @checknull mysql mysql_client_find_plugin(mysql.ptr, name, type)
end

Expand Down Expand Up @@ -1034,7 +1034,7 @@ value: A pointer to the option value.
Return Values
Zero for success, 1 if an error occurred. If the plugin has an option handler, that handler should also return zero for success and 1 if an error occurred.
"""=#
function pluginoption(plugin::Ptr{Cvoid}, option::String, value)
function pluginoption(plugin::Ptr{Cvoid}, option::AbstractString, value)
mysql_plugin_options(plugin, option, value)
end

Expand Down Expand Up @@ -1129,7 +1129,7 @@ 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::Union{String, Nothing}, db::String, port::Integer, unix_socket::String, client_flag)
function connect(mysql::MYSQL, host::AbstractString, user::AbstractString, passwd::Union{AbstractString, Nothing}, db::AbstractString, port::Integer, unix_socket::AbstractString, 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 All @@ -1145,7 +1145,7 @@ The string pointed to by from must be length bytes long. You must allocate the t
If you must change the character set of the connection, use the mysql_set_character_set() function rather than executing a SET NAMES (or SET CHARACTER SET) statement. mysql_set_character_set() works like SET NAMES but also affects the character set used by mysql_real_escape_string(), which SET NAMES does not.
"""=#
function escapestring(mysql::MYSQL, str::String)
function escapestring(mysql::MYSQL, str::AbstractString)
len = sizeof(str)
to = Base.StringVector(len * 2 + 1)
tolen = mysql_real_escape_string(mysql.ptr, to, str, len)
Expand Down Expand Up @@ -1198,7 +1198,7 @@ if (mysql_real_query(&mysql,query,(unsigned int) (end - query)))
}
The my_stpcpy() function used in the example is included in the libmysqlclient library and works like strcpy() but returns a pointer to the terminating null of the first parameter.
"""=#
function escapestringquote(mysql::MYSQL, str::String, q::Char)
function escapestringquote(mysql::MYSQL, str::AbstractString, q::Char)
len = sizeof(str)
to = Base.StringVector(len * 2 + 1)
tolen = mysql_real_escape_string_quote(mysql.ptr, to, str, len, q)
Expand All @@ -1216,7 +1216,7 @@ If you want to know whether the statement returns a result set, you can use mysq
Return Values
Zero for success. Nonzero if an error occurred.
"""=#
function query(mysql::MYSQL, sql::String)
function query(mysql::MYSQL, sql::AbstractString)
return @checksuccess mysql mysql_real_query(mysql.ptr, sql, sizeof(sql))
end

Expand Down Expand Up @@ -1321,14 +1321,14 @@ Causes the database specified by db to become the default (current) database on
mysql_select_db() fails unless the connected user can be authenticated as having permission to use the database or some object within it.
"""=#
function selectdb(mysql::MYSQL, db::String)
function selectdb(mysql::MYSQL, db::AbstractString)
return @checksuccess mysql mysql_select_db(mysql.ptr, db)
end

#="""
This function is used to set the default character set for the current connection. The string csname specifies a valid character set name. The connection collation becomes the default collation of the character set. This function works like the SET NAMES statement, but also sets the value of mysql->charset, and thus affects the character set used by mysql_real_escape_string()
"""=#
function setcharacterset(mysql::MYSQL, csname::String)
function setcharacterset(mysql::MYSQL, csname::AbstractString)
return @checksuccess mysql mysql_set_character_set(mysql.ptr, csname)
end

Expand Down Expand Up @@ -1445,7 +1445,7 @@ cipher: The list of permissible ciphers for SSL encryption.
Return Values
This function always returns 0. If SSL setup is incorrect, a subsequent mysql_real_connect() call returns an error when you attempt to connect.
"""=#
function sslset(mysql::MYSQL, key::String, cert::String, ca::String, capath::String, cipher::String)
function sslset(mysql::MYSQL, key::AbstractString, cert::AbstractString, ca::AbstractString, capath::AbstractString, cipher::AbstractString)
return mysql_ssl_set(mysql.ptr, key, cert, ca, capath, cipher)
end

Expand Down
10 changes: 5 additions & 5 deletions src/api/ccalls.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function mysql_autocommit(mysql::Ptr{Cvoid}, mode)
end

#bool mysql_change_user(MYSQL *mysql, const char *user, const char *password, const char *db)
function mysql_change_user(mysql::Ptr{Cvoid}, user::String, password::String, db)
function mysql_change_user(mysql::Ptr{Cvoid}, user::AbstractString, password::AbstractString, db)
return @c(:mysql_change_user,
Bool,
(Ptr{Cvoid}, Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}),
Expand All @@ -53,7 +53,7 @@ function mysql_character_set_name(mysql::Ptr{Cvoid})
end

#struct st_mysql_client_plugin *mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
function mysql_client_find_plugin(mysql::Ptr{Cvoid}, name::String, type::Int)
function mysql_client_find_plugin(mysql::Ptr{Cvoid}, name::AbstractString, type::Int)
return @c(:mysql_client_find_plugin,
Ptr{Cvoid},
(Ptr{Cvoid}, Ptr{UInt8}, Cint),
Expand Down Expand Up @@ -477,7 +477,7 @@ function mysql_row_tell(result::Ptr{Cvoid})
end

#int mysql_select_db(MYSQL *mysql, const char *db)
function mysql_select_db(mysql::Ptr{Cvoid}, db::String)
function mysql_select_db(mysql::Ptr{Cvoid}, db::AbstractString)
return @c(:mysql_select_db,
Cint,
(Ptr{Cvoid}, Ptr{UInt8}),
Expand All @@ -501,7 +501,7 @@ function mysql_session_track_get_next(mysql::Ptr{Cvoid}, type, data, len)
end

#int mysql_set_character_set(MYSQL *mysql, const char *csname)
function mysql_set_character_set(mysql::Ptr{Cvoid}, csname::String)
function mysql_set_character_set(mysql::Ptr{Cvoid}, csname::AbstractString)
return @c(:mysql_set_character_set,
Cint,
(Ptr{Cvoid}, Ptr{UInt8}),
Expand Down Expand Up @@ -806,4 +806,4 @@ function mysql_stmt_store_result(stmt::Ptr{Cvoid})
Cint,
(Ptr{Cvoid},),
stmt)
end
end
Loading

0 comments on commit 8a05d1c

Please sign in to comment.