I’m writing a function and I wanted to paste a list typed by user to filters in WHERE. List typed to function by user:
filters = list( ‘fruits’ = c(‘apple’,’orange’),
‘vegetables’ = ‘carrot’)
How to paste this list to sql query in glue sql:
df = glue_sql(“select …
where filters)
parts <- paste(sapply(names(filters), function(nm) sprintf("%s in ({%s*})", nm, nm)), collapse = " and ")
parts
# [1] "fruits in ({fruits*}) and vegetables in ({vegetables*})"
glue::glue_data_sql(filters, paste("select * from table where", parts), .con = con)
# <SQL> select * from table where fruits in ('apple', 'orange') and vegetables in ('carrot')
More dynamic, allowing a singular "!"
operator to negate equality/set-membership.
func <- function(nm, z) {
not <- ("!" %in% z)
z <- setdiff(z, "!")
len1 <- (length(z) == 1L)
parens <- if (len1) c("{", "}") else c("({", "*})")
op <- if (len1) {
if (not) "!=" else "="
} else {
if (not) "not in" else "in"
}
sprintf("%s %s %s setdiff(%s,'!') %s",
nm, op, parens[1], nm, parens[2])
}
filters <- list( 'fruits' = c('!','apple','orange'), 'vegetables' = c('!', 'carrot') )
paste(mapply(func, names(filters), filters), collapse = " and ")
# [1] "fruits not in ({ setdiff(fruits,'!') *}) and vegetables != { setdiff(vegetables,'!') }"
glue::glue_data_sql(filters, paste(mapply(func, names(filters), filters), collapse = " and "), .con=con)
# <SQL> fruits not in ('apple', 'orange') and vegetables != 'carrot'
filters <- list( 'fruits' = c('apple','orange'), 'vegetables' = c('carrot') )
glue::glue_data_sql(filters, paste(mapply(func, names(filters), filters), collapse = " and "), .con=con)
# <SQL> fruits in ('apple', 'orange') and vegetables = 'carrot'
The negation is based solely on the presence of the "!"
literal in a vector. (Anything more complex and you might as well adopt mongo's json-structured query language ... not something I'm eager to re-implement.)