0

Is the following a correct way to use the roxygen @import directive when defining package variables? I suspect not, because trying to use the db function yields Error in connection_quote_identifier(conn@ptr, x) : Invalid connection.

The connection should be valid. I can run the same code outside the package (after calling library(dplyr);library(RPostgres) and it works.

#' @import RPostgres
cxn <- dbConnect(Postgres(), service = 'plasticemission')

#' @import dplyr
#' @export
db <- function(name) {
  tbl(cxn, name)
}
Ian
  • 1,062
  • 1
  • 9
  • 21
  • You should not be generating connections like that, in the top level of a package source file. Consider putting the `cxn <- ...` code within the `db` function. If you really need persistence, perhaps top-level `cxn <- NULL`, and then in your `db` function: `if (is.null(cxn)) cxn <<- DBI::dbConnect(RPostgres::Postgres(), ...)`. – r2evans Jun 15 '19 at 21:28

1 Answers1

1

Extension of my comment, consider changing it to

cxn <- NULL

#' @param name character, name of the table
#' @param cxn database (DBI) connection object
#' @import DBI
#' @import RPostgres
#' @import dplyr
#' @export
db <- function(name, cxn = cxn) {
  if (missing(cxn) && is.null(cxn)) {
    cxn <<- DBI::dbConnect(RPostgres::Postgres(), service = 'plasticemission')
  }
  dplyr::tbl(cxn, name)
}

This way, you do not attempt connection instantiation when the package is loaded, just when the function is called. I provided an override-able variable cxn in the call in case you ever have need for multiple, temporary, or non-standard connections.

If you do really want it to be connected as soon as you load the package, consider using .onLoad (or .onAttach), with something like:

# it might be better defined here, not in your other function, but once is enough
cxn <- NULL

.onLoad <- function(libname, pkgname) {
  if (getOption("mypackage.autocxn", default = FALSE)) {
    if (is.null(cxn)) {
      cxn <<- DBI::dbConnect(RPostgres::Postgres(), service = 'plasticemission')
    }
  }
}

In this case, I made it an explicit requirement for auto-connect to set a global option "mypackage.autocxn" (in this case as a logical). The name of the option is completely arbitrary, and you can do all sorts of flexible things here such as

.onLoad <- function(libname, pkgname) {
  if (length(opts <- getOption("mypackage.autocxn", default = NULL)) &&
        is.null(cxn)) {
    cxn <<- do.call(DBI::dbConnect, c(list(drv = RPostgres::Postgres()), args))
  }
}

And somewhere in your personal setup (perhaps your ~/.Rprofile), you can set

```lang-r
options(mypackage.autocxn = list(service = 'plasticemission'))
```
r2evans
  • 141,215
  • 6
  • 77
  • 149