This document describes how to add a new SQL backend to dbplyr. To begin:
Ensure that you have a DBI compliant database backend. If not, you’ll need to first create it by following the instructions in
vignette("backend", package = "DBI")
.You’ll need a working knowledge of S3. Make sure that you’re familiar with the basics before you start.
This document is still a work in progress, but it will hopefully get you started. I’d also strongly recommend reading the bundled source code for SQLite, MySQL, and PostgreSQL.
First steps
For interactive exploitation, attach dplyr and DBI. If you’re creating a package, you’ll need to import dplyr and DBI.
Check that you can create a tbl from a connection, like:
con <- DBI::dbConnect(RSQLite::SQLite(), path = ":memory:")
DBI::dbWriteTable(con, "mtcars", mtcars)
tbl(con, "mtcars")
#> # Source: table<`mtcars`> [?? x 11]
#> # Database: sqlite 3.47.1 []
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
#> 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
#> 3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
#> 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
#> # ℹ more rows
If you can’t, this likely indicates some problem with the DBI methods. Use DBItest to narrow down the problem.
Write your first method
The first method of your dbplyr backend should always be for the
dbplyr_edition()
generic:
#' @importFrom dbplyr dbplyr_edition
#' @export
dbplyr_edition.myConnectionClass <- function(con) 2L
This declares that your package uses version 2 of the API, which is the version that this vignette documents.
Copying, computing, collecting and collapsing
Next, check that copy_to()
, collapse()
,
compute()
, and collect()
work:
If
copy_to()
fails, you probably need a method forsql_table_analyze()
orsql_table_index()
. Ifcopy_to()
fails during creation of the tbl, you may need a method forsql_query_fields()
.If
collapse()
fails, your database has a non-standard way of constructing subqueries. Add a method forsql_subquery()
.If
compute()
fails, your database has a non-standard way of saving queries in temporary tables. Add a method fordb_save_query()
.
SQL translation
Make sure you’ve read vignette("translation-verb")
so
you have the lay of the land.
Verbs
Check that SQL translation for the key verbs work:
-
summarise()
,mutate()
,filter()
etc: powered bysql_query_select()
-
left_join()
,inner_join()
: powered bysql_query_join()
-
semi_join()
,anti_join()
: powered bysql_query_semi_join()
-
union()
,intersect()
,setdiff()
: powered bysql_query_set_op()
Vectors
Finally, you may have to provide custom R -> SQL translation at
the vector level by providing a method for
sql_translate_env()
. This function should return an object
created by sql_variant()
. See existing methods for
examples.