Here is mtcars data in the MonetDBLite database file.
library(MonetDBLite)
library(tidyverse)
library(DBI)
dbdir <- getwd()
con <- dbConnect(MonetDBLite::MonetDBLite(), dbdir)
dbWriteTable(conn = con, name = "mtcars_1", value = mtcars)
data_mt <- con %>% tbl("mtcars_1")
I want to use dplyr mutate to create new variables and add (commit!) that to the database table? Something like
data_mt %>% select(mpg, cyl) %>% mutate(var = mpg/cyl) %>% dbCommit(con)
The desired output should be same when we do:
dbSendQuery(con, "ALTER TABLE mtcars_1 ADD COLUMN var DOUBLE PRECISION")
dbSendQuery(con, "UPDATE mtcars_1 SET var=mpg/cyl")
How can do that?
Here's a couple of functions,
createandupdate.tbl_lazy.They respectively implement
CREATE TABLE, which was straightforward, and theALTER TABLE/UPDATEpair which is much less so:CREATE
example:
UPDATE
example 1, define 2 new numeric columns :
example 2, modify an existing column, create 2 new columns of different types :
example 3, update where:
example 4 : update by group
GENERAL NOTES
The code uses uses
dbplyr::translate_sqlso we can use R functions or native ones alike just like in good oldmutatecalls.updatecan only be used after onefiltercall OR onegroup_bycall OR zero of each, anything else and you'll get an error or unexpected results.The
group_byimplementation is VERY hacky, so no room for defining columns on the fly or grouping by an operation, stick to the basics.updateandcreateboth returntbl(con, table_name), which means you can chain as manycreateorupdatecalls as you wish, with the appropriate amount ofgroup_byandfilterin between. In fact all of my 4 examples can be chained.To hammer the nail,
createdoesn't suffer from the same restrictions, you can have as muchdbplyrfun as desired before calling it.I didn't implement type detection, so I needed the
new_typeparameter, it is recycled in thepastecall of thealter_queriesdefinition in my code so it can be a single value or a vector.One way to solve the latter would be to extract the variables from the
translationsvariable, find their types indbGetQuery(con,"PRAGMA table_info(iris)"). Then we need coercion rules between all existing types, and we're set. But as different DBMS have different types I can't think of a general way to do it, and I don't knowMonetDBLite.