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/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new a9c381d2 fix(r/adbcdrivermanager): Ensure nullable arguments 
`adbc_connection_get_objects()` can be specified (#1032)
a9c381d2 is described below

commit a9c381d2203b28558739f99a8e770d6ab6a50b66
Author: Dewey Dunnington <[email protected]>
AuthorDate: Fri Sep 8 13:38:53 2023 -0300

    fix(r/adbcdrivermanager): Ensure nullable arguments 
`adbc_connection_get_objects()` can be specified (#1032)
    
    Thanks to @nbenn for the reprex!
    
    ``` r
    library(adbcdrivermanager)
    
    db <- adbc_database_init(adbcsqlite::adbcsqlite(), uri = ":memory:")
    con <- adbc_connection_init(db)
    
    flights <- nycflights13::flights
    flights$time_hour <- NULL
    
    write_adbc(flights, con, "flights")
    stream <- adbc_connection_get_objects(con)
    # pretty wild result type
    df <- as.data.frame(stream)
    df$catalog_db_schemas[[1]]$db_schema_tables[[1]]$table_name
    #> [1] "flights"
    
df$catalog_db_schemas[[1]]$db_schema_tables[[1]]$table_columns[[1]]$column_name
    #>  [1] "year"           "month"          "day"            "dep_time"
    #>  [5] "sched_dep_time" "dep_delay"      "arr_time"       "sched_arr_time"
    #>  [9] "arr_delay"      "carrier"        "flight"         "tailnum"
    #> [13] "origin"         "dest"           "air_time"       "distance"
    #> [17] "hour"           "minute"
    ```
    
    <sup>Created on 2023-09-01 with [reprex
    v2.0.2](https://reprex.tidyverse.org)</sup>
---
 r/adbcdrivermanager/R/adbc.R                       |  4 ++--
 .../man/adbc_connection_get_info.Rd                | 12 +++++------
 r/adbcdrivermanager/src/radbc.cc                   | 23 ++++++++++++++++------
 r/adbcdrivermanager/src/radbc.h                    |  6 +++++-
 4 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/r/adbcdrivermanager/R/adbc.R b/r/adbcdrivermanager/R/adbc.R
index 2e25424a..cf711e02 100644
--- a/r/adbcdrivermanager/R/adbc.R
+++ b/r/adbcdrivermanager/R/adbc.R
@@ -226,8 +226,8 @@ adbc_connection_get_info <- function(connection, 
info_codes) {
 
 #' @rdname adbc_connection_get_info
 #' @export
-adbc_connection_get_objects <- function(connection, depth, catalog, db_schema,
-                                        table_name, table_type, column_name) {
+adbc_connection_get_objects <- function(connection, depth = 0L, catalog = 
NULL, db_schema = NULL,
+                                        table_name = NULL, table_type = NULL, 
column_name = NULL) {
   error <- adbc_allocate_error()
   out_stream <- nanoarrow::nanoarrow_allocate_array_stream()
   status <- .Call(
diff --git a/r/adbcdrivermanager/man/adbc_connection_get_info.Rd 
b/r/adbcdrivermanager/man/adbc_connection_get_info.Rd
index 451a9b0f..b4fb89d9 100644
--- a/r/adbcdrivermanager/man/adbc_connection_get_info.Rd
+++ b/r/adbcdrivermanager/man/adbc_connection_get_info.Rd
@@ -14,12 +14,12 @@ adbc_connection_get_info(connection, info_codes)
 
 adbc_connection_get_objects(
   connection,
-  depth,
-  catalog,
-  db_schema,
-  table_name,
-  table_type,
-  column_name
+  depth = 0L,
+  catalog = NULL,
+  db_schema = NULL,
+  table_name = NULL,
+  table_type = NULL,
+  column_name = NULL
 )
 
 adbc_connection_get_table_schema(connection, catalog, db_schema, table_name)
diff --git a/r/adbcdrivermanager/src/radbc.cc b/r/adbcdrivermanager/src/radbc.cc
index 224c7f81..5d080cbd 100644
--- a/r/adbcdrivermanager/src/radbc.cc
+++ b/r/adbcdrivermanager/src/radbc.cc
@@ -274,10 +274,11 @@ extern "C" SEXP RAdbcConnectionGetObjects(SEXP 
connection_xptr, SEXP depth_sexp,
                                           SEXP error_xptr) {
   auto connection = adbc_from_xptr<AdbcConnection>(connection_xptr);
   int depth = adbc_as_int(depth_sexp);
-  const char* catalog = adbc_as_const_char(catalog_sexp);
-  const char* db_schema = adbc_as_const_char(db_schema_sexp);
-  const char* table_name = adbc_as_const_char(table_name_sexp);
+  const char* catalog = adbc_as_const_char(catalog_sexp, true);
+  const char* db_schema = adbc_as_const_char(db_schema_sexp, true);
+  const char* table_name = adbc_as_const_char(table_name_sexp, true);
 
+  // Build the null-terminated const char** used to filter by table type
   int table_type_length = Rf_length(table_type_sexp);
   SEXP table_type_shelter =
       PROTECT(Rf_allocVector(RAWSXP, (table_type_length + 1) * sizeof(const 
char*)));
@@ -287,12 +288,22 @@ extern "C" SEXP RAdbcConnectionGetObjects(SEXP 
connection_xptr, SEXP depth_sexp,
   }
   table_type[table_type_length] = nullptr;
 
-  const char* column_name = adbc_as_const_char(column_name_sexp);
+  // Ensure that R_NilValue maps to null and not a null-termianted const char**
+  // of length 0.
+  const char** table_type_maybe_null;
+  if (table_type_sexp == R_NilValue) {
+    table_type_maybe_null = nullptr;
+  } else {
+    table_type_maybe_null = table_type;
+  }
+
+  const char* column_name = adbc_as_const_char(column_name_sexp, true);
   auto out_stream = adbc_from_xptr<ArrowArrayStream>(out_stream_xptr);
   auto error = adbc_from_xptr<AdbcError>(error_xptr);
 
-  int status = AdbcConnectionGetObjects(connection, depth, catalog, db_schema, 
table_name,
-                                        table_type, column_name, out_stream, 
error);
+  int status =
+      AdbcConnectionGetObjects(connection, depth, catalog, db_schema, 
table_name,
+                               table_type_maybe_null, column_name, out_stream, 
error);
   UNPROTECT(1);
   return adbc_wrap_status(status);
 }
diff --git a/r/adbcdrivermanager/src/radbc.h b/r/adbcdrivermanager/src/radbc.h
index 9baf8d6d..9c20686d 100644
--- a/r/adbcdrivermanager/src/radbc.h
+++ b/r/adbcdrivermanager/src/radbc.h
@@ -131,7 +131,11 @@ static inline void adbc_xptr_move_attrs(SEXP xptr_old, 
SEXP xptr_new) {
   UNPROTECT(5);
 }
 
-static inline const char* adbc_as_const_char(SEXP sexp) {
+static inline const char* adbc_as_const_char(SEXP sexp, bool nullable = false) 
{
+  if (nullable && sexp == R_NilValue) {
+    return nullptr;
+  }
+
   if (TYPEOF(sexp) != STRSXP || Rf_length(sexp) != 1) {
     Rf_error("Expected character(1) for conversion to const char*");
   }

Reply via email to