Nothing
#' spec_meta_bind
#' @name spec_meta_bind
#' @aliases NULL
#' @family meta specifications
#' @usage NULL
#' @format NULL
#' @keywords NULL
spec_meta_bind_expr <- function(
arrow = c("none", "query"),
bind = c("df", "stream"),
...,
ctx = stop("ctx is available during run time only")) {
check_dots_empty()
arrow <- arg_match(arrow)
bind <- arg_match(bind)
out <- list(
bind_return_value = function() {
#' @return
check_return_value <- function(bind_res, res) {
#' `dbBind()` returns the result set,
expect_identical(res, bind_res$value)
#' invisibly,
expect_false(bind_res$visible)
}
#' for queries issued by [dbSendQuery()] or [dbSendQueryArrow()] and
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
check_return_value = check_return_value
)
},
#
bind_return_value_statement = if (arrow != "query") function() {
check_return_value <- function(bind_res, res) {
expect_identical(res, bind_res$value)
expect_false(bind_res$visible)
}
#' also for data manipulation statements issued by
#' [dbSendStatement()].
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
check_return_value = check_return_value,
query = FALSE
)
},
#
bind_too_many = function() {
#' @section Failure modes:
patch_bind_values <- function(bind_values) {
#' Binding too many
if (is.null(names(bind_values))) {
c(bind_values, bind_values[[1L]])
} else {
c(bind_values, bogus = bind_values[[1L]])
}
}
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
patch_bind_values = patch_bind_values,
bind_error = ".*"
)
},
#
bind_not_enough = function() {
patch_bind_values <- function(bind_values) {
#' or not enough values,
bind_values[-1L]
}
test_select_bind_expr(
arrow = arrow,
bind = bind,
1:2,
patch_bind_values = patch_bind_values,
bind_error = ".*"
)
},
#
bind_wrong_name = function() {
patch_bind_values <- function(bind_values) {
#' or parameters with wrong names
stats::setNames(bind_values, paste0("bogus", names(bind_values)))
}
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
patch_bind_values = patch_bind_values,
bind_error = ".*",
requires_names = TRUE
)
},
#
bind_multi_row_unequal_length = if (bind == "df") function() {
patch_bind_values <- function(bind_values) {
#' or unequal length,
bind_values[[2]] <- bind_values[[2]][-1]
bind_values
}
#' also raises an error.
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(1:3, 2:4),
patch_bind_values = patch_bind_values,
bind_error = ".*",
query = FALSE
)
},
#
bind_named_param_unnamed_placeholders = function() {
#' If the placeholders in the query are named,
patch_bind_values <- function(bind_values) {
#' all parameter values must have names
stats::setNames(bind_values, NULL)
}
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
patch_bind_values = patch_bind_values,
bind_error = ".*",
requires_names = TRUE
)
},
#
bind_named_param_empty_placeholders = function() {
patch_bind_values <- function(bind_values) {
#' (which must not be empty
names(bind_values)[[1]] <- ""
bind_values
}
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(1L, 2L),
patch_bind_values = patch_bind_values,
bind_error = ".*",
requires_names = TRUE
)
},
#
bind_named_param_na_placeholders = if (arrow == "none") function() {
patch_bind_values <- function(bind_values) {
#' or `NA`),
names(bind_values)[[1]] <- NA
bind_values
}
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(1L, 2L),
patch_bind_values = patch_bind_values,
bind_error = ".*",
requires_names = TRUE
)
},
bind_unnamed_param_named_placeholders = function() {
#' and vice versa,
patch_bind_values <- function(bind_values) {
stats::setNames(bind_values, letters[seq_along(bind_values)])
}
#' otherwise an error is raised.
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
patch_bind_values = patch_bind_values,
bind_error = ".*",
requires_names = FALSE
)
},
#' The behavior for mixing placeholders of different types
#' (in particular mixing positional and named placeholders)
#' is not specified.
#'
bind_premature_clear = function() {
#' Calling `dbBind()` on a result set already cleared by [dbClearResult()]
is_premature_clear <- TRUE
#' also raises an error.
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
is_premature_clear = is_premature_clear,
bind_error = ".*"
)
},
bind_multi_row = function() {
#' @section Specification:
#' The elements of the `params` argument do not need to be scalars,
#' vectors of arbitrary length
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(1:3)
)
},
#
bind_multi_row_zero_length = function() {
#' (including length 0)
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(integer(), integer()),
dbitest_version = if (arrow == "query" || bind == "stream") "1.7.99.12"
)
#' are supported.
# This behavior is tested as part of run_bind_tester$fun
#' For queries, calling `dbFetch()` binding such parameters returns
#' concatenated results, equivalent to binding and fetching for each set
#' of values and connecting via [rbind()].
},
#
bind_multi_row_statement = if (arrow != "query") function() {
# This behavior is tested as part of run_bind_tester$fun
#' For data manipulation statements, `dbGetRowsAffected()` returns the
#' total number of rows affected if binding non-scalar parameters.
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(1:3),
query = FALSE
)
},
#
bind_repeated = function() {
#' `dbBind()` also accepts repeated calls on the same result set
is_repeated <- TRUE
#' for both queries
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
is_repeated = is_repeated
)
},
#
bind_repeated_statement = if (arrow != "query") function() {
is_repeated <- TRUE
#' and data manipulation statements,
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
is_repeated = is_repeated,
query = FALSE
)
},
#
bind_repeated_untouched = function() {
#' even if no results are fetched between calls to `dbBind()`,
is_repeated <- TRUE
is_untouched <- TRUE
#' for both queries
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
is_repeated = is_repeated,
is_untouched = is_untouched
)
},
#
bind_repeated_untouched_statement = if (arrow != "query") function() {
is_repeated <- TRUE
is_untouched <- TRUE
#' and data manipulation statements.
test_select_bind_expr(
arrow = arrow,
bind = bind,
1L,
is_repeated = is_repeated,
is_untouched = is_untouched,
query = FALSE
)
},
#'
bind_named_param_shuffle = function() {
#' If the placeholders in the query are named,
patch_bind_values <- function(bind_values) {
#' their order in the `params` argument is not important.
bind_values[c(3, 1, 2, 4)]
}
test_select_bind_expr(
arrow = arrow,
bind = bind,
c(1:3 + 0.5, NA),
patch_bind_values = patch_bind_values,
requires_names = TRUE
)
},
#'
bind_integer = function() {
#' At least the following data types are accepted on input (including [NA]):
#' - [integer]
test_select_bind_expr(
arrow = arrow,
bind = bind,
c(1:3, NA)
)
},
bind_numeric = function() {
#' - [numeric]
test_select_bind_expr(
arrow = arrow,
bind = bind,
c(1:3 + 0.5, NA)
)
},
bind_logical = function() {
#' - [logical] for Boolean values
test_select_bind_expr(
arrow = arrow,
bind = bind,
c(TRUE, FALSE, NA)
)
},
bind_character = function() {
#' - [character]
test_select_bind_expr(
arrow = arrow,
bind = bind,
c(get_texts(), NA)
)
},
bind_character_escape = function() {
#' (also with special characters such as spaces, newlines, quotes, and backslashes)
test_select_bind_expr(
arrow = arrow,
bind = bind,
c(" ", "\n", "\r", "\b", "'", '"', "[", "]", "\\", NA)
)
},
bind_factor = function() {
#' - [factor] (bound as character,
#' with warning)
test_select_bind_expr(
arrow = arrow,
bind = bind,
map(c(get_texts(), NA_character_), factor),
warn = if (bind == "df") TRUE,
dbitest_version = if (arrow == "query" && bind == "df") "1.7.99.13"
)
},
bind_date = function() {
#' - [Date]
test_select_bind_expr(
arrow = arrow,
bind = bind,
c(as.Date("2023-12-17") + 0:2, NA),
skip_fun = function() !isTRUE(ctx$tweaks$date_typed)
)
},
bind_date_integer = function() {
#' (also when stored internally as integer)
test_select_bind_expr(
arrow = arrow,
bind = bind,
structure(c(18618:18620, NA), class = "Date"),
skip_fun = function() !isTRUE(ctx$tweaks$date_typed)
)
},
bind_timestamp = function() {
#' - [POSIXct] timestamps
data_in <- as.POSIXct(c(
"2023-12-17 02:40:22",
"2023-12-17 02:40:23",
"2023-12-17 02:40:24",
NA
))
test_select_bind_expr(
arrow = arrow,
bind = bind,
data_in,
skip_fun = function() !isTRUE(ctx$tweaks$timestamp_typed)
)
},
bind_timestamp_lt = function() {
#' - [POSIXlt] timestamps
data_in <- list(
as.POSIXlt(as.POSIXct("2023-12-17 02:40:49")),
as.POSIXlt(as.POSIXct("2023-12-17 02:40:50")),
as.POSIXlt(as.POSIXct("2023-12-17 02:40:51")),
as.POSIXlt(NA_character_)
)
test_select_bind_expr(
arrow = arrow,
bind = bind,
data_in,
skip_fun = function() !isTRUE(ctx$tweaks$timestamp_typed)
)
},
bind_time_seconds = function() {
#' - [difftime] values
data_in <- as.difftime(as.numeric(c(1:3, NA)), units = "secs")
test_select_bind_expr(
arrow = arrow,
bind = bind,
data_in,
skip_fun = function() !isTRUE(ctx$tweaks$time_typed)
)
},
bind_time_hours = function() {
#' (also with units other than seconds
data_in <- as.difftime(as.numeric(c(1:3, NA)), units = "hours")
test_select_bind_expr(
arrow = arrow,
bind = bind,
data_in,
skip_fun = function() !isTRUE(ctx$tweaks$time_typed)
)
},
bind_time_minutes_integer = function() {
#' and with the value stored as integer)
data_in <- as.difftime(c(1:3, NA), units = "mins")
test_select_bind_expr(
arrow = arrow,
bind = bind,
data_in,
skip_fun = function() !isTRUE(ctx$tweaks$time_typed)
)
},
bind_raw = if (bind == "df") function() {
#' - lists of [raw] for blobs (with `NULL` entries for SQL NULL values)
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(list(as.raw(1:10)), list(raw(3)), list(NULL)),
skip_fun = function() isTRUE(ctx$tweaks$omit_blob_tests),
dbitest_version = if (arrow == "query" && bind == "df") "1.7.99.14",
cast_fun = ctx$tweaks$blob_cast
)
},
bind_blob = function() {
#' - objects of type [blob::blob]
test_select_bind_expr(
arrow = arrow,
bind = bind,
list(blob::blob(as.raw(1:10)), blob::blob(raw(3)), blob::blob(NULL)),
skip_fun = function() isTRUE(ctx$tweaks$omit_blob_tests),
cast_fun = ctx$tweaks$blob_cast
)
},
#
NULL
)
infix <- get_bind_arrow_infix(arrow, bind)
names(out) <- gsub("^", infix, names(out))
out
}
get_bind_arrow_infix <- function(arrow, bind) {
if (arrow == "none") {
if (bind == "df") {
""
} else {
"stream_"
}
} else {
if (bind == "df") {
"arrow_"
} else {
"arrow_stream_"
}
}
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.