Skip to content

Create copy_to equivalent with read-only access #628

@iangow

Description

@iangow

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)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions