-
Notifications
You must be signed in to change notification settings - Fork 187
Description
I use a database server where normal users do not have TEMPORARY privileges. This means that connections to the database are read-only and functions such as compute() or dbWriteTable() are not available. I suspect that this is not uncommon in the real world.
One downside of this is that if I have data locally that I want to join with data on the server, the only real option is to collect or otherwise download data from the server. But in a typical use case, the data I have locally are small, while the data on the server are large. So this is very inefficient.
The function below is a quick fix for this issue. It basically turns a data frame into SQL and creates a remote data frame using that SQL. Its use is illustrated here. Performance is (unsurprisingly) worse than dbWriteTable, but it's not too bad.
The function below is obviously incomplete and PostgreSQL-focused (it works for my current use case), but would a function like this belong somewhere in dbplyr?
library(DBI)
library(dplyr, warn.conflicts = FALSE)
df_to_pg <- function(df, conn) {
convert_vec <- function(vec) {
if (class(vec)=="character") {
convert_char(vec)
} else if (class(vec)=="Date") {
convert_date(vec)
} else if (class(vec)=="integer") {
convert_int(vec)
} else if (class(vec)=="numeric") {
convert_num(vec)
}
}
make_string <- function(vec) {
paste0("'{", paste(paste0('"', vec, '"'), collapse=","), "}'")
}
convert_char <- function(vec) {
paste0(make_string(vec), "::text[]")
}
convert_int <- function(vec) {
paste0(make_string(vec), "::integer[]")
}
convert_date <- function(vec) {
paste0(make_string(vec), "::date[]")
}
convert_num <- function(vec) {
paste0(make_string(vec), "::float8[]")
}
temp_starter_sql <- list()
for (i in 1:length(df)) {
temp_starter_sql[[i]] = paste0("UNNEST (",
convert_vec(df[[i]]), ") AS ",
names(df)[[i]])
}
temp_sql <- paste0("SELECT ", paste0(temp_starter_sql, collapse = ",\n"))
temp_df_sql <- tbl(conn, sql(temp_sql))
return(temp_df_sql)
}