When using !is.na() in any context while submitting queries to my MSSQL Server, my ODBC driver isn't happy about a syntax error. It appears using the ~ in the query creates an issue, where the most appropriate translation for !is.na(x) should probably be x IS NOT NULL.
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(dbplyr))
lf <- lazy_frame(tibble(a = 1:10, b = 2), con = simulate_mssql())
# Fails
lf %>% mutate(c = !is.na(a))
#> <SQL>
#> SELECT *, CAST(IIF(~(`a` IS NULL), 1, 0) AS BIT) AS `c`
#> FROM `df`
# Succeeds
lf %>% mutate(c = is.na(a))
#> <SQL>
#> SELECT *, CAST(IIF((`a` IS NULL), 1, 0) AS BIT) AS `c`
#> FROM `df`
# Succeeds
lf %>% mutate(c = sql('CAST(IIF((`a` IS NOT NULL), 1, 0) AS BIT)'))
#> <SQL>
#> SELECT *, CAST(IIF((`a` IS NOT NULL), 1, 0) AS BIT) AS `c`
#> FROM `df`
Created on 2023-04-07 with reprex v2.0.2
Specifically, the error is:
Error in `collect()`:
! Failed to collect lazy table.
Caused by error:
! nanodbc/nanodbc.cpp:1752: 00000: [FreeTDS][SQL Server]Statement(s) could not be prepared. [FreeTDS][SQL Server]Incorrect syntax near 'q01'. [FreeTDS][SQL Server]Incorrect syntax near the keyword 'IS'.
<SQL> 'SELECT TOP 11 *, CAST(IIF(~("a" IS NULL), 1, 0) AS BIT) AS "c"
FROM (
SELECT *
FROM "#dbplyr_005"
) "q01"'
but when substituting with raw SQL like above, things work as expected.
I'm not sure if this is an indicator of a broader issue with how the MSSQL implementation expects to apply the "not operator" to non-existent boolean types using "bits" (MSSQL Server doesn't support booleans, which is a facepalm), but I was definitely having issues trying to invert a TRUE or 1 value in any way using ! via dbplyr.
When using
!is.na()in any context while submitting queries to my MSSQL Server, my ODBC driver isn't happy about a syntax error. It appears using the~in the query creates an issue, where the most appropriate translation for!is.na(x)should probably bex IS NOT NULL.Created on 2023-04-07 with reprex v2.0.2
Specifically, the error is:
but when substituting with raw SQL like above, things work as expected.
I'm not sure if this is an indicator of a broader issue with how the MSSQL implementation expects to apply the "not operator" to non-existent boolean types using "bits" (MSSQL Server doesn't support booleans, which is a facepalm), but I was definitely having issues trying to invert a
TRUEor1value in any way using!via dbplyr.