Skip to content

Commit

Permalink
Merge pull request #417 from r-dbi/unnamed-id
Browse files Browse the repository at this point in the history
feat: `Id()` now accepts unnamed components
  • Loading branch information
aviator-app[bot] authored Nov 8, 2023
2 parents 02c2227 + 9dd810e commit 9b88962
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 32 deletions.
35 changes: 19 additions & 16 deletions R/00-Id.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ setClass("Id", slots = list(name = "character"))
#' Refer to a table nested in a hierarchy (e.g. within a schema)
#'
#' @description
#' Objects of class `Id` have a single slot `name`, which is a named
#' character vector.
#' Objects of class `Id` have a single slot `name`, which is a character vector.
#' The [dbQuoteIdentifier()] method converts `Id` objects to strings.
#' Support for `Id` objects depends on the database backend.
#'
#' They can be used in the following methods as `name` or `table` argument:
#'
#' - [dbCreateTable()]
Expand All @@ -21,35 +21,38 @@ setClass("Id", slots = list(name = "character"))
#'
#' Objects of this class are also returned from [dbListObjects()].
#'
#' @param ... Components of the hierarchy, e.g. `schema`, `table`,
#' or `cluster`, `catalog`, `schema`, `table`,
#' depending on the database backend.
#' For more on these concepts, see
#' \url{https://stackoverflow.com/questions/7022755/}
#' @param ... Components of the hierarchy, e.g. `schema`, `table`, or `cluster`,
#' `catalog`, `schema`, `table`, depending on the database backend. For more
#' on these concepts, see <https://stackoverflow.com/questions/7022755/>
#' @export
#' @examples
#' # Identifies a table in a specific schema:
#' Id("dbo", "Customer")
#' # You can name the components if you want, but it's not needed
#' Id(schema = "dbo", table = "Customer")
#'
#' # Identifies a table in a specific cluster, catalog, and schema:
#' Id(cluster = "mycluster", catalog = "mycatalog", schema = "myschema", table = "mytable")
#'
#' # Create a SQL expression for an identifier:
#' dbQuoteIdentifier(ANSI(), Id(schema = "nycflights13", table = "flights"))
#' dbQuoteIdentifier(ANSI(), Id("nycflights13", "flights"))
#'
#' # Write a table in a specific schema:
#' \dontrun{
#' dbWriteTable(con, Id(schema = "myschema", table = "mytable"), data.frame(a = 1))
#' dbWriteTable(con, Id("myschema", "mytable"), data.frame(a = 1))
#' }
Id <- function(...) {
components <- c(...)
if (is.null(names(components)) || any(names(components) == "")) {
stop("All arguments to Id() must be named.", call. = FALSE)
if (!is.character(components)) {
stop("All elements of `...` must be strings.", call. = FALSE)
}
new("Id", name = components)

new("Id", name = c(...))
}

#' @export
toString.Id <- function(x, ...) {
paste0("<Id> ", paste0(names(x@name), " = ", x@name, collapse = ", "))
paste0("<Id> ", dbQuoteIdentifier(ANSI(), x))
}


dbQuoteIdentifier_DBIConnection_Id <- function(conn, x, ...) {
SQL(paste0(dbQuoteIdentifier(conn, x@name), collapse = "."))
}
5 changes: 1 addition & 4 deletions R/dbQuoteIdentifier_DBIConnection.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
dbQuoteIdentifier_DBIConnection <- function(conn, x, ...) {
# Don't support lists, auto-vectorization violates type stability
if (is(x, "SQL")) return(x)
if (is(x, "Id")) {
return(SQL(paste0(dbQuoteIdentifier(conn, x@name), collapse = ".")))
}
if (!is.character(x)) stop("x must be character or SQL", call. = FALSE)

if (any(is.na(x))) {
Expand Down Expand Up @@ -37,4 +34,4 @@ setMethod("dbQuoteIdentifier", signature("DBIConnection", "SQL"), dbQuoteIdentif

#' @rdname hidden_aliases
#' @export
setMethod("dbQuoteIdentifier", signature("DBIConnection", "Id"), dbQuoteIdentifier_DBIConnection)
setMethod("dbQuoteIdentifier", signature("DBIConnection", "Id"), dbQuoteIdentifier_DBIConnection_Id)
21 changes: 9 additions & 12 deletions man/Id.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions tests/testthat/_snaps/00-Id.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Id() requires a character vector

Code
Id(1)
Condition
Error:
! All elements of `...` must be strings.

# has a decent print method

Code
Id("a", "b")
Output
<Id> "a"."b"

14 changes: 14 additions & 0 deletions tests/testthat/test-00-Id.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
test_that("Id() requires a character vector", {
expect_snapshot(Id(1), error = TRUE)
})

test_that("has a decent print method", {
expect_snapshot(Id("a", "b"))
})

test_that("each element is quoted individually", {
expect_equal(
DBI::dbQuoteIdentifier(ANSI(), Id("a", "b.c")),
SQL('"a"."b.c"')
)
})

0 comments on commit 9b88962

Please sign in to comment.