Skip to content

Commit

Permalink
Support bitwise operators
Browse files Browse the repository at this point in the history
  • Loading branch information
David Hall committed Feb 6, 2019
1 parent 8cbaa92 commit 84fc0b4
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 16 deletions.
17 changes: 17 additions & 0 deletions R/backend-.R
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@ base_scalar <- sql_translator(
sql_expr(!!x %OR% !!y %AND NOT% (!!x %AND% !!y))
},

# bitwise operators
# SQL Syntax reference links:
# Hive: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-ArithmeticOperators
# Impala: https://www.cloudera.com/documentation/enterprise/5-9-x/topics/impala_bit_functions.html
# PostgreSQL: https://www.postgresql.org/docs/7.4/functions-math.html
# MS SQL: https://docs.microsoft.com/en-us/sql/t-sql/language-elements/bitwise-operators-transact-sql?view=sql-server-2017
# MySQL https://dev.mysql.com/doc/refman/5.7/en/bit-functions.html
# Oracle: https://docs.oracle.com/cd/E19253-01/817-6223/chp-typeopexpr-7/index.html
# SQLite: https://www.tutorialspoint.com/sqlite/sqlite_bitwise_operators.htm
# Teradata: https://docs.teradata.com/reader/1DcoER_KpnGTfgPinRAFUw/h3CS4MuKL1LCMQmnubeSRQ
bitwNot = function(x) sql_expr(~ !!x),
bitwAnd = function(x, y) sql_infix("&")(x, as.integer(y)),
bitwOr = function(x, y) sql_infix("|")(x, as.integer(y)),
bitwXor = function(x, y) sql_infix("^")(x, as.integer(y)),
bitwShiftL = function(x, y) sql_infix("<<")(x, as.integer(y)),
bitwShiftR = function(x, y) sql_infix(">>")(x, as.integer(y)),

abs = sql_prefix("ABS", 1),
acos = sql_prefix("ACOS", 1),
asin = sql_prefix("ASIN", 1),
Expand Down
3 changes: 3 additions & 0 deletions R/backend-hive.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
sql_translate_env.Hive <- function(con) {
sql_variant(
sql_translator(.parent = base_odbc_scalar,
bitwShiftL = function(x, y) sql_prefix("SHIFTLEFT", 2)(x, as.integer(y)),
bitwShiftR = function(x, y) sql_prefix("SHIFTRIGHT", 2)(x, as.integer(y)),

var = sql_prefix("VARIANCE"),
cot = function(x){
sql_expr(1 / tan(!!x))
Expand Down
7 changes: 7 additions & 0 deletions R/backend-impala.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
sql_translate_env.Impala <- function(con) {
sql_variant(
scalar = sql_translator(.parent = base_odbc_scalar,
bitwNot = sql_prefix("BITNOT", 1),
bitwAnd = function(x, y) sql_prefix("BITAND", 2)(x, as.integer(y)),
bitwOr = function(x, y) sql_prefix("BITOR", 2)(x, as.integer(y)),
bitwXor = function(x, y) sql_prefix("BITXOR", 2)(x, as.integer(y)),
bitwShiftL = function(x, y) sql_prefix("SHIFTLEFT", 2)(x, as.integer(y)),
bitwShiftR = function(x, y) sql_prefix("SHIFTRIGHT", 2)(x, as.integer(y)),

as.Date = sql_cast("VARCHAR(10)"),
ceiling = sql_prefix("CEIL")
) ,
Expand Down
3 changes: 3 additions & 0 deletions R/backend-mssql.R
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
`|` = mssql_generic_infix("|", "%OR%"),
`||` = mssql_generic_infix("|", "%OR%"),

bitwShiftL = sql_not_supported("bitwShiftL"),
bitwShiftR = sql_not_supported("bitwShiftR"),

`if` = mssql_sql_if,
if_else = function(condition, true, false) mssql_sql_if(condition, true, false),
ifelse = function(test, yes, no) mssql_sql_if(test, yes, no),
Expand Down
1 change: 1 addition & 0 deletions R/backend-postgres.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ postgres_round <- function(x, digits = 0L) {
sql_translate_env.PostgreSQLConnection <- function(con) {
sql_variant(
sql_translator(.parent = base_scalar,
bitwXor = function(x, y) sql_infix("#")(x, as.integer(y)),
log10 = function(x) sql_expr(log(!!x)),
log = sql_log(),
cot = sql_cot(),
Expand Down
6 changes: 6 additions & 0 deletions R/backend-teradata.R
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ sql_translate_env.Teradata <- function(con) {
sql_variant(
sql_translator(.parent = base_odbc_scalar,
`!=` = sql_infix("<>"),
bitwNot = sql_prefix("BITNOT", 1),
bitwAnd = function(x, y) sql_prefix("BITAND", 2)(x, as.integer(y)),
bitwOr = function(x, y) sql_prefix("BITOR", 2)(x, as.integer(y)),
bitwXor = function(x, y) sql_prefix("BITXOR", 2)(x, as.integer(y)),
bitwShiftL = function(x, y) sql_prefix("SHIFTLEFT", 2)(x, as.integer(y)),
bitwShiftR = function(x, y) sql_prefix("SHIFTRIGHT", 2)(x, as.integer(y)),
as.numeric = sql_cast("NUMERIC"),
as.double = sql_cast("NUMERIC"),
as.character = sql_cast("VARCHAR(MAX)"),
Expand Down
2 changes: 2 additions & 0 deletions tests/testthat/test-backend-hive.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ test_that("custom scalar & string functions translated correctly", {
translate_sql(!!enquo(x), con = simulate_hive())
}

expect_equal(trans(bitwShiftL(x, 2)), sql("SHIFTLEFT(`x`, 2)"))
expect_equal(trans(bitwShiftR(x, 2)), sql("SHIFTRIGHT(`x`, 2)"))
expect_equal(trans(cot(x)), sql("1.0 / TAN(`x`)"))
expect_equal(trans(str_replace_all(x, "old", "new")), sql("REGEXP_REPLACE(`x`, 'old', 'new')"))

Expand Down
10 changes: 8 additions & 2 deletions tests/testthat/test-backend-impala.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ test_that("custom scalar functions translated correctly", {
translate_sql(!!enquo(x), con = simulate_impala())
}

expect_equal(trans(as.Date(x)), sql("CAST(`x` AS VARCHAR(10))"))
expect_equal(trans(ceiling(x)), sql("CEIL(`x`)"))
expect_equal(trans(bitwNot(x)), sql("BITNOT(`x`)"))
expect_equal(trans(bitwAnd(x, 128)), sql("BITAND(`x`, 128)"))
expect_equal(trans(bitwOr(x, 128)), sql("BITOR(`x`, 128)"))
expect_equal(trans(bitwXor(x, 128)), sql("BITXOR(`x`, 128)"))
expect_equal(trans(bitwShiftL(x, 2)), sql("SHIFTLEFT(`x`, 2)"))
expect_equal(trans(bitwShiftR(x, 2)), sql("SHIFTRIGHT(`x`, 2)"))
expect_equal(trans(as.Date(x)), sql("CAST(`x` AS VARCHAR(10))"))
expect_equal(trans(ceiling(x)), sql("CEIL(`x`)"))

})
4 changes: 3 additions & 1 deletion tests/testthat/test-backend-mssql.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ test_that("custom scalar translated correctly", {
expect_equal(trans(substr(x, 1, 2)), sql("SUBSTRING(`x`, 1.0, 2.0)"))
expect_equal(trans(trimws(x)), sql("LTRIM(RTRIM(`x`))"))

expect_error(trans(paste(x)), sql("not available"))
expect_error(trans(bitwShiftL(x, 2)), sql("not available"))
expect_error(trans(bitwShiftR(x, 2)), sql("not available"))
expect_error(trans(paste(x)), sql("not available"))

})

Expand Down
1 change: 1 addition & 0 deletions tests/testthat/test-backend-postgres.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ test_that("custom scalar translated correctly", {
translate_sql(!!enquo(x), con = simulate_postgres())
}

expect_equal(trans(bitwXor(x, 128)), sql("`x` # 128"))
expect_equal(trans(log10(x)), sql("LOG(`x`)"))
expect_equal(trans(log(x)), sql("LN(`x`)"))
expect_equal(trans(log(x, 2)), sql("LOG(`x`) / LOG(2.0)"))
Expand Down
32 changes: 19 additions & 13 deletions tests/testthat/test-backend-teradata.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@ test_that("custom scalar translated correctly", {
translate_sql(!!enquo(x), con = simulate_teradata())
}

expect_equal(trans(x != y), sql("`x` <> `y`"))
expect_equal(trans(as.numeric(x)), sql("CAST(`x` AS NUMERIC)"))
expect_equal(trans(as.double(x)), sql("CAST(`x` AS NUMERIC)"))
expect_equal(trans(as.character(x)), sql("CAST(`x` AS VARCHAR(MAX))"))
expect_equal(trans(log(x)), sql("LN(`x`)"))
expect_equal(trans(cot(x)), sql("1 / TAN(`x`)"))
expect_equal(trans(nchar(x)), sql("CHARACTER_LENGTH(`x`)"))
expect_equal(trans(ceil(x)), sql("CEILING(`x`)"))
expect_equal(trans(ceiling(x)), sql("CEILING(`x`)"))
expect_equal(trans(atan2(x, y)), sql("ATAN2(`y`, `x`)"))
expect_equal(trans(substr(x, 1, 2)), sql("SUBSTR(`x`, 1.0, 2.0)"))

expect_error(trans(paste(x)), sql("not supported"))
expect_equal(trans(x != y), sql("`x` <> `y`"))
expect_equal(trans(bitwNot(x)), sql("BITNOT(`x`)"))
expect_equal(trans(bitwAnd(x, 128)), sql("BITAND(`x`, 128)"))
expect_equal(trans(bitwOr(x, 128)), sql("BITOR(`x`, 128)"))
expect_equal(trans(bitwXor(x, 128)), sql("BITXOR(`x`, 128)"))
expect_equal(trans(bitwShiftL(x, 2)), sql("SHIFTLEFT(`x`, 2)"))
expect_equal(trans(bitwShiftR(x, 2)), sql("SHIFTRIGHT(`x`, 2)"))
expect_equal(trans(as.numeric(x)), sql("CAST(`x` AS NUMERIC)"))
expect_equal(trans(as.double(x)), sql("CAST(`x` AS NUMERIC)"))
expect_equal(trans(as.character(x)), sql("CAST(`x` AS VARCHAR(MAX))"))
expect_equal(trans(log(x)), sql("LN(`x`)"))
expect_equal(trans(cot(x)), sql("1 / TAN(`x`)"))
expect_equal(trans(nchar(x)), sql("CHARACTER_LENGTH(`x`)"))
expect_equal(trans(ceil(x)), sql("CEILING(`x`)"))
expect_equal(trans(ceiling(x)), sql("CEILING(`x`)"))
expect_equal(trans(atan2(x, y)), sql("ATAN2(`y`, `x`)"))
expect_equal(trans(substr(x, 1, 2)), sql("SUBSTR(`x`, 1.0, 2.0)"))

expect_error(trans(paste(x)), sql("not supported"))

})

Expand Down
11 changes: 11 additions & 0 deletions tests/testthat/test-translate-math.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,14 @@ test_that("log base comes first", {
test_that("log becomes ln", {
expect_equal(translate_sql(log(x)), sql('LN(`x`)'))
})

# bitwise -----------------------------------------------------------------

test_that("bitwise operations", {
expect_equal(translate_sql(bitwNot(x)), sql("~`x`"))
expect_equal(translate_sql(bitwAnd(x, 128)), sql("`x` & 128"))
expect_equal(translate_sql(bitwOr(x, 128)), sql("`x` | 128"))
expect_equal(translate_sql(bitwXor(x, 128)), sql("`x` ^ 128"))
expect_equal(translate_sql(bitwShiftL(x, 2)), sql("`x` << 2"))
expect_equal(translate_sql(bitwShiftR(x, 2)), sql("`x` >> 2"))
})

0 comments on commit 84fc0b4

Please sign in to comment.