You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sedona.apache.org by pa...@apache.org on 2026/06/18 19:53:36 UTC
(sedona-db) branch main updated: feat(r/sdplyr): Add filter translation (#972)
This is an automated email from the ASF dual-hosted git repository.
paleolimbot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sedona-db.git
The following commit(s) were added to refs/heads/main by this push:
new e034a38b9 feat(r/sdplyr): Add filter translation (#972)
e034a38b9 is described below
commit e034a38b930350b943da96850f661317452346eb
Author: Dewey Dunnington <de...@dunnington.ca>
AuthorDate: Thu Jun 18 19:53:31 2026 +0000
feat(r/sdplyr): Add filter translation (#972)
---
r/sdplyr/DESCRIPTION | 2 +-
r/sdplyr/NAMESPACE | 1 +
r/sdplyr/R/filter.R | 28 ++++++++
r/sdplyr/man/sdplyr-package.Rd | 5 ++
r/sdplyr/tests/testthat/_snaps/filter.md | 8 +++
r/sdplyr/tests/testthat/test-filter.R | 98 ++++++++++++++++++++++++++
r/sedonadb/DESCRIPTION | 2 +-
r/sedonadb/NAMESPACE | 3 +
r/sedonadb/R/000-wrappers.R | 21 ++++++
r/sedonadb/R/expression.R | 26 +++++++
r/sedonadb/man/dot-fns.Rd | 5 --
r/sedonadb/man/dot-tables.Rd | 5 --
r/sedonadb/man/sd_expr_column.Rd | 9 +++
r/sedonadb/man/sd_read_sf.Rd | 4 +-
r/sedonadb/man/sedonadb-package.Rd | 5 ++
r/sedonadb/man/sedonadb_adbc.Rd | 2 +-
r/sedonadb/src/init.c | 20 ++++++
r/sedonadb/src/rust/api.h | 3 +
r/sedonadb/src/rust/src/expression.rs | 15 ++++
r/sedonadb/tests/testthat/_snaps/expression.md | 16 +++++
r/sedonadb/tests/testthat/test-expression.R | 10 +++
r/sedonafns/DESCRIPTION | 2 +-
r/sedonafns/man/sedonafns-package.Rd | 5 ++
23 files changed, 279 insertions(+), 16 deletions(-)
diff --git a/r/sdplyr/DESCRIPTION b/r/sdplyr/DESCRIPTION
index f8f4f3159..ce0b8b303 100644
--- a/r/sdplyr/DESCRIPTION
+++ b/r/sdplyr/DESCRIPTION
@@ -16,5 +16,5 @@ Imports:
tibble
Suggests:
testthat (>= 3.0.0)
-RoxygenNote: 7.3.3
Config/testthat/edition: 3
+Config/roxygen2/version: 8.0.0
diff --git a/r/sdplyr/NAMESPACE b/r/sdplyr/NAMESPACE
index f51d07a8d..8fe4f374d 100644
--- a/r/sdplyr/NAMESPACE
+++ b/r/sdplyr/NAMESPACE
@@ -5,6 +5,7 @@ S3method(dplyr::arrange,sedonadb_dataframe)
S3method(dplyr::collect,sedonadb_dataframe)
S3method(dplyr::compute,sedonadb_dataframe)
S3method(dplyr::cross_join,sedonadb_dataframe)
+S3method(dplyr::filter,sedonadb_dataframe)
S3method(dplyr::full_join,sedonadb_dataframe)
S3method(dplyr::group_by,sedonadb_dataframe)
S3method(dplyr::inner_join,sedonadb_dataframe)
diff --git a/r/sdplyr/R/filter.R b/r/sdplyr/R/filter.R
new file mode 100644
index 000000000..e86204204
--- /dev/null
+++ b/r/sdplyr/R/filter.R
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+#' @exportS3Method dplyr::filter
+filter.sedonadb_dataframe <- function(
+ .data,
+ ...,
+ .by = sdplyr_unsupported(),
+ .preserve = sdplyr_unsupported()
+) {
+ assert_unsupported(.by, .preserve)
+ exprs <- rlang::enquos(...)
+ sedonadb::sd_filter(.data, !!!exprs)
+}
diff --git a/r/sdplyr/man/sdplyr-package.Rd b/r/sdplyr/man/sdplyr-package.Rd
index afb1cb017..0c8f1d258 100644
--- a/r/sdplyr/man/sdplyr-package.Rd
+++ b/r/sdplyr/man/sdplyr-package.Rd
@@ -11,5 +11,10 @@ Provides a 'dplyr' backend implemented using 'SedonaDB'.
\author{
\strong{Maintainer}: Dewey Dunnington \email{dewey@dunnington.ca}
+Authors:
+\itemize{
+ \item Dewey Dunnington \email{dewey@dunnington.ca}
+}
+
}
\keyword{internal}
diff --git a/r/sdplyr/tests/testthat/_snaps/filter.md b/r/sdplyr/tests/testthat/_snaps/filter.md
new file mode 100644
index 000000000..8d8a95614
--- /dev/null
+++ b/r/sdplyr/tests/testthat/_snaps/filter.md
@@ -0,0 +1,8 @@
+# filter(..., .by) is unsupported
+
+ Argument `.by` is not supported by sdplyr.
+
+# filter(..., .preserve) is unsupported
+
+ Argument `.preserve` is not supported by sdplyr.
+
diff --git a/r/sdplyr/tests/testthat/test-filter.R b/r/sdplyr/tests/testthat/test-filter.R
new file mode 100644
index 000000000..c8214004e
--- /dev/null
+++ b/r/sdplyr/tests/testthat/test-filter.R
@@ -0,0 +1,98 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+test_that("filter() works for sedonadb_dataframe", {
+ df <- tibble(x = c(3L, 1L, 2L), y = c("c", "a", "b"))
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x > 1L) |> arrange(x) |> collect(),
+ df |> filter(x > 1L) |> arrange(x)
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x == 2L) |> arrange(x) |> collect(),
+ df |> filter(x == 2L) |> arrange(x)
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(y == "a") |> arrange(x) |> collect(),
+ df |> filter(y == "a") |> arrange(x)
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x != 1L) |> arrange(x) |> collect(),
+ df |> filter(x != 1L) |> arrange(x)
+ )
+})
+
+test_that("filter() works with multiple conditions", {
+ df <- tibble(x = c(1L, 1L, 2L, 2L), y = c(4L, 3L, 2L, 1L))
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x == 1L, y > 3L) |> arrange(x) |> collect(),
+ df |> filter(x == 1L, y > 3L) |> arrange(x)
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x >= 1L, y <= 2L) |> arrange(x) |> collect(),
+ df |> filter(x >= 1L, y <= 2L) |> arrange(x)
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x == 1L | y == 1L) |> arrange(x) |> collect(),
+ df |> filter(x == 1L | y == 1L) |> arrange(x)
+ )
+})
+
+test_that("filter() handles NA values", {
+ df <- tibble(x = c(2L, NA, 1L, NA, 3L))
+
+ # Comparisons with NA return NA (falsy), so rows with NA are filtered out
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x > 1L) |> collect(),
+ df |> filter(x > 1L)
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(x == 2L) |> collect(),
+ df |> filter(x == 2L)
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(is.na(x)) |> collect(),
+ df |> filter(is.na(x))
+ )
+
+ expect_identical(
+ df |> as_sedonadb_dataframe() |> filter(!is.na(x)) |> collect(),
+ df |> filter(!is.na(x))
+ )
+})
+
+test_that("filter(..., .by) is unsupported", {
+ df <- tibble(x = 1:3, g = c("a", "a", "b"))
+ expect_snapshot_error(
+ df |> as_sedonadb_dataframe() |> filter(x > 1L, .by = "g")
+ )
+})
+
+test_that("filter(..., .preserve) is unsupported", {
+ df <- tibble(x = 1:3)
+ expect_snapshot_error(
+ df |> as_sedonadb_dataframe() |> filter(x > 1L, .preserve = TRUE)
+ )
+})
diff --git a/r/sedonadb/DESCRIPTION b/r/sedonadb/DESCRIPTION
index d1e77dbb2..8e0866444 100644
--- a/r/sedonadb/DESCRIPTION
+++ b/r/sedonadb/DESCRIPTION
@@ -8,7 +8,6 @@ Description: Provides bindings for Apache SedonaDB, a lightweight
License: Apache License (>= 2)
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
-RoxygenNote: 7.3.3
SystemRequirements: Cargo (Rust's package manager), rustc
Depends: R (>= 4.1.0)
Suggests:
@@ -29,3 +28,4 @@ Config/testthat/edition: 3
Config/build/bootstrap: TRUE
Config/Needs/check:
lintr
+Config/roxygen2/version: 8.0.0
diff --git a/r/sedonadb/NAMESPACE b/r/sedonadb/NAMESPACE
index 08ecfb04b..36b70048e 100644
--- a/r/sedonadb/NAMESPACE
+++ b/r/sedonadb/NAMESPACE
@@ -71,8 +71,11 @@ export(sd_expr_binary)
export(sd_expr_cast)
export(sd_expr_column)
export(sd_expr_factory)
+export(sd_expr_is_not_null)
+export(sd_expr_is_null)
export(sd_expr_literal)
export(sd_expr_negative)
+export(sd_expr_not)
export(sd_expr_parse_binary)
export(sd_expr_scalar_function)
export(sd_filter)
diff --git a/r/sedonadb/R/000-wrappers.R b/r/sedonadb/R/000-wrappers.R
index 0550890bc..95c9058dc 100644
--- a/r/sedonadb/R/000-wrappers.R
+++ b/r/sedonadb/R/000-wrappers.R
@@ -477,12 +477,30 @@ class(`InternalDataFrame`) <- c(
}
}
+`SedonaDBExpr_is_not_null` <- function(self) {
+ function() {
+ .savvy_wrap_SedonaDBExpr(.Call(savvy_SedonaDBExpr_is_not_null__impl, `self`))
+ }
+}
+
+`SedonaDBExpr_is_null` <- function(self) {
+ function() {
+ .savvy_wrap_SedonaDBExpr(.Call(savvy_SedonaDBExpr_is_null__impl, `self`))
+ }
+}
+
`SedonaDBExpr_negate` <- function(self) {
function() {
.savvy_wrap_SedonaDBExpr(.Call(savvy_SedonaDBExpr_negate__impl, `self`))
}
}
+`SedonaDBExpr_not` <- function(self) {
+ function() {
+ .savvy_wrap_SedonaDBExpr(.Call(savvy_SedonaDBExpr_not__impl, `self`))
+ }
+}
+
`SedonaDBExpr_parse_binary` <- function(self) {
function() {
.Call(savvy_SedonaDBExpr_parse_binary__impl, `self`)
@@ -508,7 +526,10 @@ class(`InternalDataFrame`) <- c(
e$`cast` <- `SedonaDBExpr_cast`(ptr)
e$`debug_string` <- `SedonaDBExpr_debug_string`(ptr)
e$`display` <- `SedonaDBExpr_display`(ptr)
+ e$`is_not_null` <- `SedonaDBExpr_is_not_null`(ptr)
+ e$`is_null` <- `SedonaDBExpr_is_null`(ptr)
e$`negate` <- `SedonaDBExpr_negate`(ptr)
+ e$`not` <- `SedonaDBExpr_not`(ptr)
e$`parse_binary` <- `SedonaDBExpr_parse_binary`(ptr)
e$`qualified_name` <- `SedonaDBExpr_qualified_name`(ptr)
e$`variant_name` <- `SedonaDBExpr_variant_name`(ptr)
diff --git a/r/sedonadb/R/expression.R b/r/sedonadb/R/expression.R
index 29e1b322d..0fdeca194 100644
--- a/r/sedonadb/R/expression.R
+++ b/r/sedonadb/R/expression.R
@@ -72,6 +72,24 @@ sd_expr_negative <- function(expr, factory = sd_expr_factory()) {
as_sd_expr(expr, factory = factory)$negate()
}
+#' @rdname sd_expr_column
+#' @export
+sd_expr_is_null <- function(expr, factory = sd_expr_factory()) {
+ as_sd_expr(expr, factory = factory)$is_null()
+}
+
+#' @rdname sd_expr_column
+#' @export
+sd_expr_is_not_null <- function(expr, factory = sd_expr_factory()) {
+ as_sd_expr(expr, factory = factory)$is_not_null()
+}
+
+#' @rdname sd_expr_column
+#' @export
+sd_expr_not <- function(expr, factory = sd_expr_factory()) {
+ as_sd_expr(expr, factory = factory)$not()
+}
+
#' @rdname sd_expr_column
#' @export
sd_expr_any_function <- function(
@@ -427,6 +445,14 @@ ensure_translations_registered <- function() {
sd_register_datafusion_fn(fn_name)
}
+ sd_register_translation("base::is.na", function(.ctx, x) {
+ sd_expr_is_null(x, factory = .ctx$factory)
+ })
+
+ sd_register_translation("base::!", function(.ctx, x) {
+ sd_expr_not(x, factory = .ctx$factory)
+ })
+
sd_register_translation("base::abs", function(.ctx, x) {
sd_expr_scalar_function("abs", list(x), factory = .ctx$factory)
})
diff --git a/r/sedonadb/man/dot-fns.Rd b/r/sedonadb/man/dot-fns.Rd
index 4912b4492..dbb4fd463 100644
--- a/r/sedonadb/man/dot-fns.Rd
+++ b/r/sedonadb/man/dot-fns.Rd
@@ -1,12 +1,8 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/expression.R
-\docType{data}
\name{.fns}
\alias{.fns}
\title{SedonaDB Functions}
-\format{
-An object of class \code{sedonadb_fns} of length 0.
-}
\usage{
.fns
}
@@ -15,4 +11,3 @@ This object is an escape hatch for calling SedonaDB/DataFusion functions
directly for translations that are not yet registered or are otherwise
misbehaving.
}
-\keyword{datasets}
diff --git a/r/sedonadb/man/dot-tables.Rd b/r/sedonadb/man/dot-tables.Rd
index 48da875cd..bb0bb32f6 100644
--- a/r/sedonadb/man/dot-tables.Rd
+++ b/r/sedonadb/man/dot-tables.Rd
@@ -1,12 +1,8 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/join-expression.R
-\docType{data}
\name{.tables}
\alias{.tables}
\title{SedonaDB Table Qualifiers}
-\format{
-An object of class \code{sedonadb_tables} of length 2.
-}
\usage{
.tables
}
@@ -14,4 +10,3 @@ An object of class \code{sedonadb_tables} of length 2.
This object is an escape hatch for referring to the right or left side
of a join when constructing \code{\link[=sd_join_by]{sd_join_by()}} or \code{\link[=sd_join_select]{sd_join_select()}} expressions.
}
-\keyword{datasets}
diff --git a/r/sedonadb/man/sd_expr_column.Rd b/r/sedonadb/man/sd_expr_column.Rd
index cbadf4e72..d198447c2 100644
--- a/r/sedonadb/man/sd_expr_column.Rd
+++ b/r/sedonadb/man/sd_expr_column.Rd
@@ -5,6 +5,9 @@
\alias{sd_expr_literal}
\alias{sd_expr_binary}
\alias{sd_expr_negative}
+\alias{sd_expr_is_null}
+\alias{sd_expr_is_not_null}
+\alias{sd_expr_not}
\alias{sd_expr_any_function}
\alias{sd_expr_scalar_function}
\alias{sd_expr_aggregate_function}
@@ -24,6 +27,12 @@ sd_expr_binary(op, lhs, rhs, factory = sd_expr_factory())
sd_expr_negative(expr, factory = sd_expr_factory())
+sd_expr_is_null(expr, factory = sd_expr_factory())
+
+sd_expr_is_not_null(expr, factory = sd_expr_factory())
+
+sd_expr_not(expr, factory = sd_expr_factory())
+
sd_expr_any_function(
function_name,
args,
diff --git a/r/sedonadb/man/sd_read_sf.Rd b/r/sedonadb/man/sd_read_sf.Rd
index 7622ccc59..aab23b65c 100644
--- a/r/sedonadb/man/sd_read_sf.Rd
+++ b/r/sedonadb/man/sd_read_sf.Rd
@@ -31,7 +31,7 @@ sd_ctx_read_sf(
)
}
\arguments{
-\item{dsn, layer}{Description of datasource and layer. See \code{\link[sf:st_read]{sf::read_sf()}}
+\item{dsn, layer}{Description of datasource and layer. See \code{\link[sf:read_sf]{sf::read_sf()}}
for details.}
\item{...}{Currently unused and must be empty}
@@ -46,7 +46,7 @@ form "KEY=VALUE".}
\item{filter}{A spatial object that may be used to filter while reading.
In the future SedonaDB will automatically calculate this value based on
the query. May be any spatial object that can be converted to WKT via
-\code{\link[wk:wkt]{wk::as_wkt()}}. This filter's CRS must match that of the data.}
+\code{\link[wk:as_wkt]{wk::as_wkt()}}. This filter's CRS must match that of the data.}
\item{fid_column_name}{An optional name for the feature id (FID) column.}
diff --git a/r/sedonadb/man/sedonadb-package.Rd b/r/sedonadb/man/sedonadb-package.Rd
index 6503612dd..6bd792007 100644
--- a/r/sedonadb/man/sedonadb-package.Rd
+++ b/r/sedonadb/man/sedonadb-package.Rd
@@ -11,5 +11,10 @@ Provides bindings for Apache SedonaDB, a lightweight query engine optimized for
\author{
\strong{Maintainer}: Dewey Dunnington \email{dewey@dunnington.ca}
+Authors:
+\itemize{
+ \item Dewey Dunnington \email{dewey@dunnington.ca}
+}
+
}
\keyword{internal}
diff --git a/r/sedonadb/man/sedonadb_adbc.Rd b/r/sedonadb/man/sedonadb_adbc.Rd
index e75e9566a..3db3958fa 100644
--- a/r/sedonadb/man/sedonadb_adbc.Rd
+++ b/r/sedonadb/man/sedonadb_adbc.Rd
@@ -7,7 +7,7 @@
sedonadb_adbc()
}
\value{
-An \code{\link[adbcdrivermanager:adbc_driver_void]{adbcdrivermanager::adbc_driver()}} of class
+An \code{\link[adbcdrivermanager:adbc_driver]{adbcdrivermanager::adbc_driver()}} of class
'sedonadb_driver_sedonadb'
}
\description{
diff --git a/r/sedonadb/src/init.c b/r/sedonadb/src/init.c
index eb1be1708..400782db7 100644
--- a/r/sedonadb/src/init.c
+++ b/r/sedonadb/src/init.c
@@ -291,11 +291,26 @@ SEXP savvy_SedonaDBExpr_display__impl(SEXP self__) {
return handle_result(res);
}
+SEXP savvy_SedonaDBExpr_is_not_null__impl(SEXP self__) {
+ SEXP res = savvy_SedonaDBExpr_is_not_null__ffi(self__);
+ return handle_result(res);
+}
+
+SEXP savvy_SedonaDBExpr_is_null__impl(SEXP self__) {
+ SEXP res = savvy_SedonaDBExpr_is_null__ffi(self__);
+ return handle_result(res);
+}
+
SEXP savvy_SedonaDBExpr_negate__impl(SEXP self__) {
SEXP res = savvy_SedonaDBExpr_negate__ffi(self__);
return handle_result(res);
}
+SEXP savvy_SedonaDBExpr_not__impl(SEXP self__) {
+ SEXP res = savvy_SedonaDBExpr_not__ffi(self__);
+ return handle_result(res);
+}
+
SEXP savvy_SedonaDBExpr_parse_binary__impl(SEXP self__) {
SEXP res = savvy_SedonaDBExpr_parse_binary__ffi(self__);
return handle_result(res);
@@ -436,8 +451,13 @@ static const R_CallMethodDef CallEntries[] = {
(DL_FUNC)&savvy_SedonaDBExpr_debug_string__impl, 1},
{"savvy_SedonaDBExpr_display__impl",
(DL_FUNC)&savvy_SedonaDBExpr_display__impl, 1},
+ {"savvy_SedonaDBExpr_is_not_null__impl",
+ (DL_FUNC)&savvy_SedonaDBExpr_is_not_null__impl, 1},
+ {"savvy_SedonaDBExpr_is_null__impl",
+ (DL_FUNC)&savvy_SedonaDBExpr_is_null__impl, 1},
{"savvy_SedonaDBExpr_negate__impl",
(DL_FUNC)&savvy_SedonaDBExpr_negate__impl, 1},
+ {"savvy_SedonaDBExpr_not__impl", (DL_FUNC)&savvy_SedonaDBExpr_not__impl, 1},
{"savvy_SedonaDBExpr_parse_binary__impl",
(DL_FUNC)&savvy_SedonaDBExpr_parse_binary__impl, 1},
{"savvy_SedonaDBExpr_qualified_name__impl",
diff --git a/r/sedonadb/src/rust/api.h b/r/sedonadb/src/rust/api.h
index 357c6854b..18cdeb12f 100644
--- a/r/sedonadb/src/rust/api.h
+++ b/r/sedonadb/src/rust/api.h
@@ -86,7 +86,10 @@ SEXP savvy_SedonaDBExpr_alias__ffi(SEXP self__, SEXP c_arg__name);
SEXP savvy_SedonaDBExpr_cast__ffi(SEXP self__, SEXP c_arg__schema_xptr);
SEXP savvy_SedonaDBExpr_debug_string__ffi(SEXP self__);
SEXP savvy_SedonaDBExpr_display__ffi(SEXP self__);
+SEXP savvy_SedonaDBExpr_is_not_null__ffi(SEXP self__);
+SEXP savvy_SedonaDBExpr_is_null__ffi(SEXP self__);
SEXP savvy_SedonaDBExpr_negate__ffi(SEXP self__);
+SEXP savvy_SedonaDBExpr_not__ffi(SEXP self__);
SEXP savvy_SedonaDBExpr_parse_binary__ffi(SEXP self__);
SEXP savvy_SedonaDBExpr_qualified_name__ffi(SEXP self__);
SEXP savvy_SedonaDBExpr_variant_name__ffi(SEXP self__);
diff --git a/r/sedonadb/src/rust/src/expression.rs b/r/sedonadb/src/rust/src/expression.rs
index 9063e5d3a..6ea129423 100644
--- a/r/sedonadb/src/rust/src/expression.rs
+++ b/r/sedonadb/src/rust/src/expression.rs
@@ -87,6 +87,21 @@ impl SedonaDBExpr {
Ok(Self { inner })
}
+ fn is_null(&self) -> savvy::Result<SedonaDBExpr> {
+ let inner = Expr::IsNull(Box::new(self.inner.clone()));
+ Ok(Self { inner })
+ }
+
+ fn not(&self) -> savvy::Result<SedonaDBExpr> {
+ let inner = Expr::Not(Box::new(self.inner.clone()));
+ Ok(Self { inner })
+ }
+
+ fn is_not_null(&self) -> savvy::Result<SedonaDBExpr> {
+ let inner = Expr::IsNotNull(Box::new(self.inner.clone()));
+ Ok(Self { inner })
+ }
+
fn variant_name(&self) -> savvy::Result<savvy::Sexp> {
self.inner.variant_name().try_into()
}
diff --git a/r/sedonadb/tests/testthat/_snaps/expression.md b/r/sedonadb/tests/testthat/_snaps/expression.md
index 76eee19ec..d30b51b13 100644
--- a/r/sedonadb/tests/testthat/_snaps/expression.md
+++ b/r/sedonadb/tests/testthat/_snaps/expression.md
@@ -256,6 +256,22 @@
<SedonaDBExpr>
abs(x)
+# nulls can be checked via is.na()
+
+ Code
+ sd_eval_expr(quote(is.na(x)))
+ Output
+ <SedonaDBExpr>
+ x IS NULL
+
+# ! is translated to NOT
+
+ Code
+ sd_eval_expr(quote(!x))
+ Output
+ <SedonaDBExpr>
+ NOT x
+
# errors that occur during evaluation have reasonable context
Code
diff --git a/r/sedonadb/tests/testthat/test-expression.R b/r/sedonadb/tests/testthat/test-expression.R
index 9b8d829c5..91e2c3e94 100644
--- a/r/sedonadb/tests/testthat/test-expression.R
+++ b/r/sedonadb/tests/testthat/test-expression.R
@@ -135,6 +135,16 @@ test_that("basic set of numeric functions are translated", {
expect_snapshot(sd_eval_expr(quote(abs(x))))
})
+test_that("nulls can be checked via is.na()", {
+ x <- sd_expr_column("x")
+ expect_snapshot(sd_eval_expr(quote(is.na(x))))
+})
+
+test_that("! is translated to NOT", {
+ x <- sd_expr_column("x")
+ expect_snapshot(sd_eval_expr(quote(!x)))
+})
+
test_that("errors that occur during evaluation have reasonable context", {
function_without_a_translation <- function(x) x + 1L
expect_snapshot(sd_eval_expr(quote(stop("this will error"))), error = TRUE)
diff --git a/r/sedonafns/DESCRIPTION b/r/sedonafns/DESCRIPTION
index 5ecbe5102..7a7a66fec 100644
--- a/r/sedonafns/DESCRIPTION
+++ b/r/sedonafns/DESCRIPTION
@@ -7,7 +7,6 @@ Description: Provides function definitions and documentation for use in 'SedonaD
License: Apache License (>= 2)
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
-RoxygenNote: 7.3.3
Depends: R (>= 4.1.0)
Suggests:
sedonadb,
@@ -20,3 +19,4 @@ Config/Needs/build:
roxygen2,
yaml
Config/testthat/edition: 3
+Config/roxygen2/version: 8.0.0
diff --git a/r/sedonafns/man/sedonafns-package.Rd b/r/sedonafns/man/sedonafns-package.Rd
index 76962fb26..8691f1d76 100644
--- a/r/sedonafns/man/sedonafns-package.Rd
+++ b/r/sedonafns/man/sedonafns-package.Rd
@@ -11,5 +11,10 @@ Provides function definitions and documentation for use in 'SedonaDB'.
\author{
\strong{Maintainer}: Dewey Dunnington \email{dewey@dunnington.ca}
+Authors:
+\itemize{
+ \item Dewey Dunnington \email{dewey@dunnington.ca}
+}
+
}
\keyword{internal}