Skip to content

dbDriver("name")

4 messages · Hadley Wickham, Paul Gilbert

#
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.

Hadley
#
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:

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
#
On 13-10-22 09:30 AM, Hadley Wickham wrote:
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
#
Oh, probably not. I've changed it to use:

is_attached <- function(x) {
  x %in% loadedNamespaces()
}
I do a similar thing in dplyr when looking for test databases - I
think it's probably relatively common task for package authors, but
less common for package users.

Hadley