This is an automated email from the ASF dual-hosted git repository.

lidavidm 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 49ba460b feat(r): Add quoting/escaping generics (#1083)
49ba460b is described below

commit 49ba460b6965835c8a4e9caae535e930fcd206cb
Author: Dewey Dunnington <[email protected]>
AuthorDate: Wed Sep 20 16:33:07 2023 +0200

    feat(r): Add quoting/escaping generics (#1083)
    
    Closes #1066.
    
    This may be superceeded at some point to use the versions provided by
    some APIs and/or something we build into the drivers; however, we don't
    have access to the low-level pointers (e.g., `PGconn*`) outside the C
    driver implementations that would be required to leverage something like
    libpq's `PQescapeidentifier()`.
    
    This implementation was inspired by RSQLite (
    
https://github.com/r-dbi/RSQLite/blob/main/R/dbQuoteIdentifier_SQLiteConnection_character.R#L9-L21
    ) but leaves the details of "marking" output as `SQL()` to something at
    a higher level (i.e., this generic is just a chance for the driver to
    perform a transformation).
    
    I don't think we ship any drivers at the moment that don't use the
    standard SQL quoting mechanism (e.g., MySQL or Access); however, I'm
    happy to implement specializations in other driver packages if this
    comes up.
---
 r/adbcdrivermanager/NAMESPACE                      |  4 ++++
 r/adbcdrivermanager/R/adbc.R                       | 25 ++++++++++++++++++++++
 .../man/adbc_connection_get_info.Rd                | 11 ++++++++++
 r/adbcdrivermanager/tests/testthat/test-radbc.R    | 10 +++++++++
 4 files changed, 50 insertions(+)

diff --git a/r/adbcdrivermanager/NAMESPACE b/r/adbcdrivermanager/NAMESPACE
index f49b8ced..f594bd3b 100644
--- a/r/adbcdrivermanager/NAMESPACE
+++ b/r/adbcdrivermanager/NAMESPACE
@@ -9,6 +9,8 @@ S3method("[[<-",adbc_xptr)
 S3method(adbc_connection_init,adbc_database_log)
 S3method(adbc_connection_init,adbc_database_monkey)
 S3method(adbc_connection_init,default)
+S3method(adbc_connection_quote_identifier,default)
+S3method(adbc_connection_quote_string,default)
 S3method(adbc_database_init,adbc_driver_log)
 S3method(adbc_database_init,adbc_driver_monkey)
 S3method(adbc_database_init,default)
@@ -36,6 +38,8 @@ export(adbc_connection_get_table_types)
 export(adbc_connection_init)
 export(adbc_connection_init_default)
 export(adbc_connection_join)
+export(adbc_connection_quote_identifier)
+export(adbc_connection_quote_string)
 export(adbc_connection_read_partition)
 export(adbc_connection_release)
 export(adbc_connection_rollback)
diff --git a/r/adbcdrivermanager/R/adbc.R b/r/adbcdrivermanager/R/adbc.R
index cf711e02..53756f41 100644
--- a/r/adbcdrivermanager/R/adbc.R
+++ b/r/adbcdrivermanager/R/adbc.R
@@ -192,6 +192,7 @@ adbc_connection_release <- function(connection) {
 #' @param column_name Only show columns with the given name. If NULL, do not
 #'   filter by name. May be a search pattern.
 #' @param serialized_partition The partition descriptor.
+#' @param value A string or identifier.
 #'
 #' @return
 #'   - `adbc_connection_get_info()`, `adbc_connection_get_objects()`,
@@ -302,6 +303,30 @@ adbc_connection_commit <- function(connection) {
   invisible(connection)
 }
 
+#' @rdname adbc_connection_get_info
+#' @export
+adbc_connection_quote_identifier <- function(connection, value, ...) {
+  UseMethod("adbc_connection_quote_identifier")
+}
+
+#' @rdname adbc_connection_get_info
+#' @export
+adbc_connection_quote_string <- function(connection, value, ...) {
+  UseMethod("adbc_connection_quote_string")
+}
+
+#' @export
+adbc_connection_quote_identifier.default <- function(connection, value, ...) {
+  out <- gsub('"', '""', enc2utf8(value))
+  paste0('"', out, '"')
+}
+
+#' @export
+adbc_connection_quote_string.default <- function(connection, value, ...) {
+  out <- gsub("'", "''", enc2utf8(value))
+  paste0("'", out, "'")
+}
+
 #' @rdname adbc_connection_get_info
 #' @export
 adbc_connection_rollback <- function(connection) {
diff --git a/r/adbcdrivermanager/man/adbc_connection_get_info.Rd 
b/r/adbcdrivermanager/man/adbc_connection_get_info.Rd
index b4fb89d9..12f5afa5 100644
--- a/r/adbcdrivermanager/man/adbc_connection_get_info.Rd
+++ b/r/adbcdrivermanager/man/adbc_connection_get_info.Rd
@@ -7,6 +7,8 @@
 \alias{adbc_connection_get_table_types}
 \alias{adbc_connection_read_partition}
 \alias{adbc_connection_commit}
+\alias{adbc_connection_quote_identifier}
+\alias{adbc_connection_quote_string}
 \alias{adbc_connection_rollback}
 \title{Connection methods}
 \usage{
@@ -30,6 +32,10 @@ adbc_connection_read_partition(connection, 
serialized_partition)
 
 adbc_connection_commit(connection)
 
+adbc_connection_quote_identifier(connection, value, ...)
+
+adbc_connection_quote_string(connection, value, ...)
+
 adbc_connection_rollback(connection)
 }
 \arguments{
@@ -61,6 +67,11 @@ GetTableTypes. Terminate the list with a NULL entry.}
 filter by name. May be a search pattern.}
 
 \item{serialized_partition}{The partition descriptor.}
+
+\item{value}{A string or identifier.}
+
+\item{...}{Driver-specific options. For the default method, these are
+named values that are converted to strings.}
 }
 \value{
 \itemize{
diff --git a/r/adbcdrivermanager/tests/testthat/test-radbc.R 
b/r/adbcdrivermanager/tests/testthat/test-radbc.R
index e7aa4bda..1ee83660 100644
--- a/r/adbcdrivermanager/tests/testthat/test-radbc.R
+++ b/r/adbcdrivermanager/tests/testthat/test-radbc.R
@@ -75,6 +75,16 @@ test_that("connection methods work for the void driver", {
     adbc_connection_rollback(con),
     con
   )
+
+  expect_identical(
+    adbc_connection_quote_identifier(con, 'some"identifier'),
+    '"some""identifier"'
+  )
+
+  expect_identical(
+    adbc_connection_quote_string(con, "some'value"),
+    "'some''value'"
+  )
 })
 
 test_that("can initialize and release a statement", {

Reply via email to