diff --git a/R/backend-snowflake.R b/R/backend-snowflake.R index 9e5d203e4..70e9dcbc9 100644 --- a/R/backend-snowflake.R +++ b/R/backend-snowflake.R @@ -164,25 +164,25 @@ sql_translation.Snowflake <- function(con) { sql_expr(EXTRACT("year", !!x)) }, seconds = function(x) { - glue_sql2(sql_current_con(), "INTERVAL '{x} second'") + snowflake_interval_sql(x, "second") }, minutes = function(x) { - glue_sql2(sql_current_con(), "INTERVAL '{x} minute'") + snowflake_interval_sql(x, "minute") }, hours = function(x) { - glue_sql2(sql_current_con(), "INTERVAL '{x} hour'") + snowflake_interval_sql(x, "hour") }, days = function(x) { - glue_sql2(sql_current_con(), "INTERVAL '{x} day'") + snowflake_interval_sql(x, "day") }, weeks = function(x) { - glue_sql2(sql_current_con(), "INTERVAL '{x} week'") + snowflake_interval_sql(x, "week") }, months = function(x) { - glue_sql2(sql_current_con(), "INTERVAL '{x} month'") + snowflake_interval_sql(x, "month") }, years = function(x) { - glue_sql2(sql_current_con(), "INTERVAL '{x} year'") + snowflake_interval_sql(x, "year") }, # https://docs.snowflake.com/en/sql-reference/functions/date_trunc.html floor_date = function(x, unit = "seconds") { @@ -300,4 +300,8 @@ snowflake_pmin_pmax_builder <- function(dot_1, dot_2, comparison){ glue_sql2(sql_current_con(), glue("COALESCE(IFF({dot_2} {comparison} {dot_1}, {dot_2}, {dot_1}), {dot_2}, {dot_1})")) } +snowflake_interval_sql <- function(x, interval_pd, con = sql_current_con()){ + glue_sql2(con, "INTERVAL '{escape(x, con = con)} {interval_pd}'") +} + utils::globalVariables(c("%REGEXP%", "DAYNAME", "DECODE", "FLOAT", "MONTHNAME", "POSITION", "trim")) diff --git a/tests/testthat/test-backend-snowflake.R b/tests/testthat/test-backend-snowflake.R index 12ce81d79..8df8d8ea2 100644 --- a/tests/testthat/test-backend-snowflake.R +++ b/tests/testthat/test-backend-snowflake.R @@ -94,6 +94,15 @@ test_that("custom lubridate functions translated correctly", { expect_equal(test_translate_sql(months(x)), sql("INTERVAL '`x` month'")) expect_equal(test_translate_sql(years(x)), sql("INTERVAL '`x` year'")) + # numeric arguments are correctly escaped in translation to SQL + expect_equal(test_translate_sql(seconds(1)), sql("INTERVAL '1.0 second'")) + expect_equal(test_translate_sql(minutes(1)), sql("INTERVAL '1.0 minute'")) + expect_equal(test_translate_sql(hours(1)), sql("INTERVAL '1.0 hour'")) + expect_equal(test_translate_sql(days(1)), sql("INTERVAL '1.0 day'")) + expect_equal(test_translate_sql(weeks(1)), sql("INTERVAL '1.0 week'")) + expect_equal(test_translate_sql(months(1)), sql("INTERVAL '1.0 month'")) + expect_equal(test_translate_sql(years(1)), sql("INTERVAL '1.0 year'")) + expect_equal(test_translate_sql(floor_date(x, "month")), sql("DATE_TRUNC('month', `x`)")) expect_equal(test_translate_sql(floor_date(x, "week")), sql("DATE_TRUNC('week', `x`)")) })