I had to make a couple of small modifications to @moodymudskipper's solution to get it to work. This was using Oracle.
unite.tbl <- function (data, col, ..., sep = "_", remove = TRUE)
{
# remove the list call
dot_names <- sapply(substitute(...)[-1], deparse)
shown_cols <- if (remove)
# replace $ops$vars with colnames
setdiff(data %>% colnames(), dot_names)
else data %>% colnames()
shown_col_str <- paste(shown_cols, collapse = ", ")
concat_str <- paste(dot_names, collapse = paste0(" || '", sep, "' || "))
col <- deparse(substitute(col))
# remove type arg
subquery <- capture.output(show_query(data))[-1] %>% paste(collapse = " ")
query <- paste(
"SELECT", shown_col_str, ",",
concat_str, "AS", col,
"FROM (",
subquery,
")"
)
tbl(data$src$con, sql(query))
}
What I need to add for my use case is a way for NA and/or NULL to be ignored, as the na.rm arg from tidyr::unite does.
EDIT: And here is the version with an na.rm argument. I did need the list wrapper around .... This may need adapted for other RDBMSs than Oracle.
unite.tbl <- function (data, col, ..., sep = "_", remove = TRUE, na.rm = FALSE)
{
dot_names <- sapply(substitute(list(...))[-1], deparse)
shown_cols <- data %>% colnames()
shown_cols <- `if`(
remove,
setdiff(shown_cols, dot_names),
shown_cols
)
shown_col_str <- paste(shown_cols, collapse = ", ")
concat_str <- ifelse(
na.rm,
paste0(
paste0(
"NVL2(",
dot_names%>% head(-1), ", ",
dot_names%>% head(-1), " || '", sep, "'",
", '')",
collapse = " || "
),
" || NVL(", dot_names%>% tail(1), ", '')"
),
paste0(dot_names, collapse = paste0(" || '", sep, "' || "))
)
col <- deparse(substitute(col))
subquery <- capture.output(show_query(data))[-1] %>% paste(collapse = " ")
query <- paste(
"SELECT", shown_col_str, ",",
concat_str, "AS", col,
"FROM (",
subquery,
")"
)
tbl(data$src$con, sql(query))
}