В конце концов я придумал свой ответ. Я опубликую его здесь, может быть когда-нибудь кому-нибудь пригодится.
Я просто повторно использовал функцию интерполяции из sql функции двигателя из knitr
(можно найти здесь ) чтобы определить мою функцию:
require('DBI')
require('knitr')
require('glue')
# Return char vector of sql interpolation param names
varnames_from_sql = function(conn = ANSI(), sql) {
varPos = DBI::sqlParseVariables(conn, sql)
if (length(varPos$start) > 0) {
varNames = substring(sql, varPos$start, varPos$end)
sub('^\\?', '', varNames)
}
}
# Vectorized version of exists
mexists = function(x, env = knit_global(), inherits = TRUE) {
vapply(x, exists, logical(1), where = env, inherits = inherits)
}
# Interpolate a sql query based on the variables in an environment
interpolate_from_env = function(conn = ANSI(), sql, env = knit_global(), inherits = TRUE) {
names = unique(varnames_from_sql(conn, sql))
names_missing = names[!mexists(names, env, inherits)]
if (length(names_missing) > 0) {
stop("Object(s) not found: ", paste('"', names_missing, '"', collapse = ", "))
}
args = if (length(names) > 0) setNames(
mget(names, envir = env, inherits = inherits), names
)
do.call(DBI::sqlInterpolate, c(list(conn, sql), args))
}
Затем я могу назвать это своим выражением SQL, чтобы получить правильное значение:
interpolate_from_env(sql = "select * from ?table_name
where color = ?color_value
?if_I_want_names and name in (?names_choices_sql)
limit ?limit_value")
, которое возвращает ожидаемый результат:
выберите * из цветов
, где цвет = 'красный'
- и имя в ('роза', 'тюльпан')
предел 10
Примечание :
этот метод потребует надлежащей предварительной оценки ваших переменных с использованием glue_sql()
. В этом случае:
table_name <- glue_sql("flowers")
color_value <- "red"
names_choices <-
names_choices_sql <- glue_sql("{c("rose", "tulip")*}", # the {}* allows to collapse a vector in SQL format
.con = ANSI())
if_I_want_names <- glue_sql("--")
limit_value <- 10