On 13-10-22 09:30 AM, Hadley Wickham wrote:
Thanks for the suggestion, however, I remain a bit confused. The function
find_driver() seems like a direct replacement for dbConnect(), using a
string to identify the database driver. You would be supporting what is a
bad idea, and just changing the name of the function, which is a make work
project for everyone.
So unless we want to invent a completely new way of registering
drivers, it seems like patching dbDriver to use this strategy will be
effective. However, I think we should equally encourage people to use
the driver object directly, instead of the string. That doesn't help
you, but it does help people only concerned with connecting to one
database.
Here's a first stab at it. I think it should work for the majority of
existing packages, regardless of whether they're loaded or not:
I'm not sure if it is a good idea or not to find drivers that are not
loaded or attached. This may cause more problems than it adds
simplifications? Would you load or attach the packages in which the
drivers are found? You and others probably understand the implications
better than I do.
Possibly one of my comments initiated the findDriver() effort, so let me
give the context in which I have been doing something a bit similar. I
look through a list of loaded/attached packages for a particular
database, with a function called like this:
con <- TSfinddb(dbname="ets",
driverOrder=c("MySQL", "SQLite", "PostgreSQL"))
which attempts a dbConnect for each driver string, looking for the
database "ets". But I just look though attached or loaded packages and
the database may not exist even if the package is loaded, so I need to
wrap the dbConnect calls in try().
(There is some risk that this is a distraction relative to more
important things that need to be done on DBI. Please don't spend a lot
of time on findDriver motivated only by my remarks.)
Paul
setMethod("dbDriver", "character",
definition = function(drvName, ...) {
findDriver(drvName)(...)
}
)
findDriver <- function(drvName) {
# If it exists in the global environment, use that
d <- get2(drvName, globalenv())
if (!is.null(d)) return(d)
# Otherwise, see if the appropriately named package is available
if (has_namespace(drvName)) {
d <- get2(drvName, asNamespace(drvName))
if (!is.null(d)) return(d)
}
pkgName <- paste0("R", drvName)
# First, see if package with name R + drvName is available
if (has_namespace(pkgName)) {
d <- get2(drvName, asNamespace(pkgName))
if (!is.null(d)) return(d)
}
# Can't find it:
stop("Couldn't find driver ", drvName, ". Looked in:\n",
"* global namespace\n",
"* in package called ", drvName, "\n",
"* in package called ", pkgName,
call. = FALSE)
}
get2 <- function(x, env) {
if (!exists(x, envir = env)) return(NULL)
get(x, envir = env)
}
has_namespace <- function(x) {
suppressMessages(requireNamespace(x, quietly = TRUE))
}
Hadley
_______________________________________________
R-sig-DB mailing list -- R Special Interest Group
R-sig-DB@r-project.org
https://stat.ethz.ch/mailman/listinfo/r-sig-db