Skip to content

Commit

Permalink
Merge branch 'main' into fetch-row-count
Browse files Browse the repository at this point in the history
  • Loading branch information
hadley authored Nov 7, 2023
2 parents 87eb831 + 3a58c37 commit 2eeae9e
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 12 deletions.
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,10 @@ exportMethods(dbClearResult)
exportMethods(dbColumnInfo)
exportMethods(dbCommit)
exportMethods(dbConnect)
exportMethods(dbCreateTable)
exportMethods(dbDataType)
exportMethods(dbDisconnect)
exportMethods(dbExecute)
exportMethods(dbExistsTable)
exportMethods(dbFetch)
exportMethods(dbGetInfo)
Expand Down
5 changes: 3 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* `dbGetRowCount()` and `dbHasComplete()` now return correct values when you
try to fetch more rows than actually exist (#501).

* Now supports `dbAppendTable()` (#539), `dbCreateTable()` (#483),
and `dbExecute` (#502).

* `dbWriteTable()` now correct uses the `billing` value set in the
connection (#486).

* Now supports `dbAppendTable()` (#539).

* `dbReadTable()`, `dbWriteTable()`, `dbExistsTable()`, `dbRemoveTable()`,
and `dbListFields()` now all work with `DBI::Id()` (#537).

Expand Down
44 changes: 44 additions & 0 deletions R/dbi-connection.R
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,26 @@ setMethod(
BigQueryResult(conn, statement, ...)
})


#' @rdname DBI
#' @inheritParams DBI::dbSendQuery
#' @export
setMethod("dbExecute", c("BigQueryConnection", "character"), function(conn, statement, ...) {
ds <- if (!is.null(conn@dataset)) as_bq_dataset(conn)

job <- bq_perform_query(statement,
billing = conn@billing,
default_dataset = ds,
quiet = conn@quiet,
...
)
bq_job_wait(job, quiet = conn@quiet)

meta <- bq_job_meta(job, "statistics(query(numDmlAffectedRows))")
as.numeric(meta$statistics$query$numDmlAffectedRows %||% 0)
})


#' @rdname DBI
#' @inheritParams DBI::dbQuoteString
#' @export
Expand Down Expand Up @@ -239,6 +259,30 @@ setMethod("dbAppendTable", c("BigQueryConnection", "character", "data.frame"), d
#' @export
setMethod("dbAppendTable", c("BigQueryConnection", "Id", "data.frame"), dbAppendTable_bq)

dbCreateTable_bq <- function(conn,
name,
fields,
...,
row.names = NULL,
temporary = FALSE) {
if (!identical(temporary, FALSE)) {
stop("Temporary tables not supported by bigrquery", call. = FALSE)
}

tb <- as_bq_table(conn, name)
bq_table_create(tb, fields)

invisible(TRUE)
}

#' @inheritParams DBI::dbCreateTable
#' @rdname DBI
#' @export
setMethod("dbCreateTable", "BigQueryConnection", dbCreateTable_bq)

#' @rdname DBI
#' @export
setMethod("dbCreateTable", "BigQueryConnection", dbCreateTable_bq)

dbReadTable_bq <- function(conn, name, ...) {
tb <- as_bq_table(conn, name)
Expand Down
17 changes: 17 additions & 0 deletions man/DBI.Rd

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

35 changes: 25 additions & 10 deletions tests/testthat/test-dbi-connection.R
Original file line number Diff line number Diff line change
Expand Up @@ -70,34 +70,49 @@ test_that("can roundtrip a data frame", {
expect_equal(ncol(df), 11)
})

test_that("can execute a query", {
tb <- bq_test_table()
con <- DBI::dbConnect(bq_dataset(tb$project, tb$dataset))

DBI::dbWriteTable(con, tb$table, data.frame(x = 1:4))
out <- dbExecute(con, glue("UPDATE {tb$table} SET x = x + 1 WHERE true"))
expect_equal(out, 4)

out <- dbExecute(con, glue("DELETE {tb$table} WHERE x <= 3"))
expect_equal(out, 2)
})

test_that("can use DBI::Id()", {
ds <- bq_test_dataset()
con <- DBI::dbConnect(ds)

df <- data.frame(x = 1:10)
id <- DBI::Id(table = "mytable")

expect_no_error(DBI::dbWriteTable(con, id, df))
expect_no_error(DBI::dbCreateTable(con, id, df))
expect_no_error(DBI::dbAppendTable(con, id, df))
expect_no_error(DBI::dbWriteTable(con, id, df, overwrite = TRUE))
expect_no_error(DBI::dbReadTable(con, id))
expect_true(DBI::dbExistsTable(con, id))
expect_no_error(DBI::dbListFields(con, id))
expect_no_error(DBI::dbRemoveTable(con, id))
})

test_that("can append to an existing dataset", {
ds <- bq_test_dataset()
con <- DBI::dbConnect(ds)
test_that("can create an empty dataset then append to it", {
tb <- bq_test_table()
con <- DBI::dbConnect(bq_dataset(tb$project, tb$dataset))

df <- data.frame(x = 1, y = 2)
DBI::dbWriteTable(con, "df", df)
DBI::dbWriteTable(con, "df", df, append = TRUE)
DBI::dbCreateTable(con, tb$table, df)
expect_equal(bq_table_nrow(tb), 0)

# Or with dbAppend
DBI::dbAppendTable(con, "df", df)
# With dbWriteTable
DBI::dbWriteTable(con, tb$table, df, append = TRUE)
expect_equal(bq_table_nrow(tb), 1)

df2 <- DBI::dbReadTable(con, "df")
expect(nrow(df2), 3L)
# Or with dbAppend
DBI::dbAppendTable(con, tb$table, df)
expect_equal(bq_table_nrow(tb), 2)
})

test_that("dataset is optional", {
Expand Down

0 comments on commit 2eeae9e

Please sign in to comment.