test_that("dplyr.strict_sql = TRUE prevents auto conversion", {
  withr::local_options(dplyr.strict_sql = TRUE)
  local_con(simulate_dbi())

  expect_equal(test_translate_sql(1 + 2), sql("1.0 + 2.0"))
  expect_snapshot(error = TRUE, {
    test_translate_sql(blah(x))
    test_translate_sql(x %blah% y)
  })
})

test_that("namespace calls are translated", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(dplyr::n(), window = FALSE), sql("COUNT(*)"))
  expect_equal(test_translate_sql(base::ceiling(x)), sql("CEIL(`x`)"))

  expect_snapshot(error = TRUE, {
    test_translate_sql(NOSUCHPACKAGE::foo())
    test_translate_sql(dbplyr::NOSUCHFUNCTION())
    test_translate_sql(base::abbreviate(x))
  })

  lz <- lazy_frame(x = 1)
  # Also test full pipeline to ensure that they make it through partial_eval
  expect_snapshot(error = TRUE, {
    lz %>% mutate(x = NOSUCHPACKAGE::foo())
    lz %>% mutate(x = dbplyr::NOSUCHFUNCTION())
    lz %>% mutate(x = base::abbreviate(x))
  })
})

test_that("Wrong number of arguments raises error", {
  local_con(simulate_dbi())
  expect_error(test_translate_sql(mean(1, 2, na.rm = TRUE), window = FALSE), "unused argument")
})

test_that("between translated to special form (#503)", {
  local_con(simulate_dbi())
  out <- test_translate_sql(between(x, 1, 2))
  expect_equal(out, sql("`x` BETWEEN 1.0 AND 2.0"))
})

test_that("%in% translation parenthesises when needed", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(x %in% 1L), sql("`x` IN (1)"))
  expect_equal(test_translate_sql(x %in% c(1L)), sql("`x` IN (1)"))
  expect_equal(test_translate_sql(x %in% 1:2), sql("`x` IN (1, 2)"))
  expect_equal(test_translate_sql(x %in% y), sql("`x` IN `y`"))
})

test_that("%in% strips vector names", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(x %in% c(a = 1L)), sql("`x` IN (1)"))
  expect_equal(test_translate_sql(x %in% !!c(a = 1L)), sql("`x` IN (1)"))
})

test_that("%in% with empty vector", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(x %in% !!integer()), sql("FALSE"))
})

test_that("n_distinct(x) translated to COUNT(distinct, x)", {
  local_con(simulate_dbi())
  expect_equal(
    test_translate_sql(n_distinct(x), window = FALSE),
    sql("COUNT(DISTINCT `x`)")
  )
  expect_equal(
    test_translate_sql(n_distinct(x), window = TRUE),
    sql("COUNT(DISTINCT `x`) OVER ()")
  )
  expect_error(test_translate_sql(n_distinct(x, y), window = FALSE), "unused argument")
})

test_that("na_if is translated to NULLIF (#211)", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(na_if(x, 0L)), sql("NULLIF(`x`, 0)"))
})

test_that("connection affects quoting character", {
  lf <- lazy_frame(field1 = 1, field2 = 2, con = simulate_sqlite())
  out <- select(lf, field1)
  expect_match(sql_render(out), "^SELECT `field1`\nFROM `df`$")
})

test_that("magrittr pipe is translated", {
  local_con(simulate_dbi())
  expect_identical(test_translate_sql(1 %>% is.na()), test_translate_sql(is.na(1)))
})

test_that("user infix functions are translated", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(x %like% y), sql("`x` like `y`"))

  # keep case and also works with vectors of length > 1 #1299
  expect_equal(test_translate_sql(x %LIKE% 1:2), sql("`x` LIKE (1, 2)"))
})

test_that("sql() evaluates input locally", {
  local_con(simulate_dbi())
  a <- "x"
  expect_equal(test_translate_sql(a), sql("`a`"))
  expect_equal(test_translate_sql(sql(a)), sql("x"))

  f <- function() {
    a <- "y"
    test_translate_sql(sql(paste0(a)))
  }
  expect_equal(f(), sql("y"))
})

test_that("sql() evaluates input locally in across()", {
  lf <- lazy_frame(x = 1, y = 2)

  expect_equal(
    lf %>%
      summarise(
        across(x, ~ sql(gsub("x","y",cur_column())))
      ) %>%
      remote_query(),
    sql("SELECT y AS `x`\nFROM `df`")
  )
})

# casts -------------------------------------------------------------------

test_that("casts as expected", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(as.integer64(x)), sql("CAST(`x` AS BIGINT)"))
  expect_equal(test_translate_sql(as.logical(x)),   sql("CAST(`x` AS BOOLEAN)"))
  expect_equal(test_translate_sql(as.Date(x)),      sql("CAST(`x` AS DATE)"))
})

# numeric -----------------------------------------------------------------

test_that("hypergeometric functions use manual calculation", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(cosh(x)), sql("(EXP(`x`) + EXP(-(`x`))) / 2"))
  expect_equal(test_translate_sql(sinh(x)), sql("(EXP(`x`) - EXP(-(`x`))) / 2"))
  expect_equal(test_translate_sql(tanh(x)), sql("(EXP(2 * (`x`)) - 1) / (EXP(2 * (`x`)) + 1)"))
  expect_equal(test_translate_sql(coth(x)), sql("(EXP(2 * (`x`)) + 1) / (EXP(2 * (`x`)) - 1)"))
})

test_that("pmin and max use GREATEST and LEAST", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(pmin(x, y, z, na.rm = TRUE)), sql("LEAST(`x`, `y`, `z`)"))
  expect_equal(test_translate_sql(pmax(x, y, na.rm = TRUE)), sql("GREATEST(`x`, `y`)"))
})

test_that("round uses integer digits", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(round(10.1)), sql("ROUND(10.1, 0)"))
  expect_equal(test_translate_sql(round(10.1, digits = 1)),  sql("ROUND(10.1, 1)"))
})

# string functions --------------------------------------------------------

test_that("paste() translated to CONCAT_WS", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(paste0(x, y)),             sql("CONCAT_WS('', `x`, `y`)"))
  expect_equal(test_translate_sql(paste(x, y)),              sql("CONCAT_WS(' ', `x`, `y`)"))
  expect_equal(test_translate_sql(paste(x, y, sep = ",")),   sql("CONCAT_WS(',', `x`, `y`)"))
})

# stringr -------------------------------------------

test_that("str_length() translates correctly ", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(str_length(x)), sql("LENGTH(`x`)"))
})

test_that("lower/upper translates correctly ", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(str_to_upper(x)), sql("UPPER(`x`)"))
  expect_equal(test_translate_sql(str_to_lower(x)), sql("LOWER(`x`)"))
})

test_that("str_trim() translates correctly ", {
  local_con(simulate_dbi())
  expect_equal(
    test_translate_sql(str_trim(x, "both")),
    sql("LTRIM(RTRIM(`x`))")
  )
  expect_equal(test_translate_sql(str_trim(x, "left")), sql("LTRIM(`x`)"))
  expect_equal(test_translate_sql(str_trim(x, "right")), sql("RTRIM(`x`)"))
})

# subsetting --------------------------------------------------------------

test_that("[ treated as if it is logical subsetting", {
  local_con(simulate_dbi())
  expect_equal(test_translate_sql(y[x == 0L]), sql("CASE WHEN (`x` = 0) THEN (`y`) END"))
})

