Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Connections now inherit from "MySQLConnection" if a MySQL server is detected (server version < 10.0). The new mysql argument to dbConnect() allows overriding the autodetection #303

Merged
merged 9 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export(mariadbHasDefault)
exportClasses(MariaDBConnection)
exportClasses(MariaDBDriver)
exportClasses(MariaDBResult)
exportClasses(MySQLConnection)
exportMethods(dbAppendTable)
exportMethods(dbBegin)
exportMethods(dbBind)
Expand Down
31 changes: 27 additions & 4 deletions R/MariaDBConnection.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
#' Class MariaDBConnection.
#'
#' `MariaDBConnection` objects are usually created by
#' [DBI::dbConnect()]
#' `"MariaDBConnection"` objects are usually created by [DBI::dbConnect()].
#' They represent a connection to a MariaDB or MySQL database.
#'
#' The `"MySQLConnection"` class is a subclass of `"MariaDBConnection"`.
#' Objects of that class are created by `dbConnect(MariaDB(), ..., mysql = TRUE)`
#' to indicate that the server is a MySQL server.
#' The \pkg{RMariaDB} package supports both MariaDB and MySQL servers, but the SQL dialect
#' and other details vary.
#' The default is to detect the server type based on the version number.
#'
#' The older \pkg{RMySQL} package also implements the `"MySQLConnection"` class.
#' The S4 system is able to distinguish between \pkg{RMariaDB} and \pkg{RMySQL} objects
#' even if both packages are loaded.
#'
#' @export
#' @keywords internal
setClass("MariaDBConnection",
MariaDBConnection <- setClass("MariaDBConnection",
contains = "DBIConnection",
slots = list(
ptr = "externalptr",
Expand All @@ -18,6 +28,19 @@ setClass("MariaDBConnection",
)
)

#' @exportClass MariaDBConnection
NULL

#' @keywords internal
#' @name MariaDBConnection-class
#' @aliases MySQLConnection-class
MySQLConnection <- setClass("MySQLConnection",
contains = "MariaDBConnection"
)

#' @exportClass MySQLConnection
NULL

# format()
#' @export
#' @rdname MariaDBConnection-class
Expand Down
50 changes: 42 additions & 8 deletions R/dbConnect_MariaDBDriver.R
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@
#' @param reconnect (experimental) Set to `TRUE` to use `MYSQL_OPT_RECONNECT` to enable
#' automatic reconnection. This is experimental and could be dangerous if the connection
#' is lost in the middle of a transaction.
#' @param mysql Set to `TRUE`/`FALSE` to connect to a MySQL server or to a MariaDB server,
#' respectively.
#' The \pkg{RMariaDB} package supports both MariaDB and MySQL servers, but the SQL dialect
#' and other details vary.
#' The default is to assume MariaDB if the version is >= 10.0.0, and MySQL otherwise.
#'
#' @references
#' Configuration files: https://mariadb.com/kb/en/library/configuring-mariadb-with-mycnf/
#' @examples
Expand Down Expand Up @@ -108,13 +114,31 @@
#' }
#' @usage NULL
#' @rdname dbConnect-MariaDBDriver-method
dbConnect_MariaDBDriver <- function(drv, dbname = NULL, username = NULL, password = NULL, host = NULL,
unix.socket = NULL, port = 0, client.flag = 0,
groups = "rs-dbi", default.file = NULL, ssl.key = NULL, ssl.cert = NULL,
ssl.ca = NULL, ssl.capath = NULL, ssl.cipher = NULL, ...,
load_data_local_infile = FALSE,
bigint = c("integer64", "integer", "numeric", "character"),
timeout = 10, timezone = "+00:00", timezone_out = NULL, reconnect = FALSE) {
dbConnect_MariaDBDriver <- function(
drv,
dbname = NULL,
username = NULL,
password = NULL,
host = NULL,
unix.socket = NULL,
port = 0,
client.flag = 0,
groups = "rs-dbi",
default.file = NULL,
ssl.key = NULL,
ssl.cert = NULL,
ssl.ca = NULL,
ssl.capath = NULL,
ssl.cipher = NULL,
...,
load_data_local_infile = FALSE,
bigint = c("integer64", "integer", "numeric", "character"),
timeout = 10,
timezone = "+00:00",
timezone_out = NULL,
reconnect = FALSE,
mysql = NULL) {
#
bigint <- match.arg(bigint)

if (is.infinite(timeout)) {
Expand Down Expand Up @@ -157,7 +181,17 @@ dbConnect_MariaDBDriver <- function(drv, dbname = NULL, username = NULL, passwor

info <- connection_info(ptr)

conn <- new("MariaDBConnection",
if (is.null(mysql)) {
mysql <- (info$db.version.int < 100000)
}

if (isTRUE(mysql)) {
new <- MySQLConnection
} else {
new <- MariaDBConnection
}

conn <- new(
ptr = ptr,
host = info$host,
db = info$dbname,
Expand Down
28 changes: 27 additions & 1 deletion R/default.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,30 @@ mariadbDefault <- function() {
},
error = function(...) {
testthat::skip("Test database not available")
})
}
)
}

mysqlDefault <- function() {
tryCatch(
{
mariadb_default(mysql = TRUE)
},
error = function(...) {
testthat::skip("Test database not available")
}
)
}

mariadbForceDefault <- function() {
tryCatch(
{
mariadb_default(mysql = FALSE)
},
error = function(...) {
testthat::skip("Test database not available")
}
)
}

mariadb_default <- function(...) {
Expand All @@ -47,5 +70,8 @@ mariadb_default <- function(...) {

mariadb_default_args <- as.list(c(
dbname = "test",
# host = "192.168.64.2",
# user = "compose",
# password = "YourStrong!Passw0rd",
NULL
))
19 changes: 17 additions & 2 deletions man/MariaDBConnection-class.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion man/dbConnect-MariaDBDriver-method.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/DbConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ cpp11::list DbConnection::info() {
"dbname"_nm = std::string(pConn_->db ? pConn_->db : ""),
"con.type"_nm = std::string(mysql_get_host_info(pConn_)),
"db.version"_nm = std::string(mysql_get_server_info(pConn_)),
"db.version.int"_nm = (int) mysql_get_server_version(pConn_),
"port"_nm = NA_INTEGER,
"protocol.version"_nm = (int) mysql_get_proto_info(pConn_),
"thread.id"_nm = (int) mysql_thread_id(pConn_)
Expand Down
22 changes: 22 additions & 0 deletions tests/testthat/test-dbConnect.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
test_that("Connecting with mysql = FALSE", {
con <- mariadbForceDefault()
on.exit(dbDisconnect(con))

expect_s4_class(con, "MariaDBConnection")
expect_false(is(con, "MySQLConnection"))
})

test_that("Connecting with mysql = TRUE", {
con <- mysqlDefault()
on.exit(dbDisconnect(con))

expect_s4_class(con, "MariaDBConnection")
expect_s4_class(con, "MySQLConnection")
})

test_that("Connecting with mysql unset", {
con <- mariadbDefault()
on.exit(dbDisconnect(con))

expect_s4_class(con, "MariaDBConnection")
})
Loading