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", {