Skip to content

Commit

Permalink
Force field type when appending to unexisting table (Fix #2206)
Browse files Browse the repository at this point in the history
This fix only applies to `RPostgres` driver.
  • Loading branch information
etiennebr committed Aug 29, 2023
1 parent 732525f commit ac0a1dd
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 23 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -565,5 +565,6 @@ importFrom(utils,packageVersion)
importFrom(utils,str)
importFrom(utils,tail)
importMethodsFrom(DBI,dbDataType)
importMethodsFrom(DBI,dbExistsTable)
importMethodsFrom(DBI,dbWriteTable)
useDynLib(sf, .registration=TRUE)
33 changes: 19 additions & 14 deletions R/db.R
Original file line number Diff line number Diff line change
Expand Up @@ -466,22 +466,27 @@ setMethod("dbWriteTable", c("PostgreSQLConnection", "character", "sf"),
#' to PostgreSQL. See `dbDataType()` for details.
#' @md
#' @rdname dbWriteTable
#' @importMethodsFrom DBI dbWriteTable
#' @importMethodsFrom DBI dbWriteTable dbExistsTable
#' @export
setMethod("dbWriteTable", c("DBIObject", "character", "sf"),
function(conn, name, value, ..., row.names = FALSE, overwrite = FALSE,
append = FALSE, field.types = NULL, binary = TRUE) {
if (is.null(field.types)) field.types <- dbDataType(conn, value)
# DBI cannot set field types with append
if (append) field.types <- NULL
#tryCatch({
dbWriteTable(conn, name, to_postgis(conn, value, binary),..., row.names = row.names,
overwrite = overwrite, append = append,
field.types = field.types)
# }, warning=function(w) {
# stop(conditionMessage(w), call. = FALSE) # nocov
# })
}
function(conn, name, value, ..., row.names = FALSE, overwrite = FALSE,
append = FALSE, field.types = NULL, binary = TRUE) {
if (is.null(field.types)) field.types <- dbDataType(conn, value)

# DBI cannot set field types with append, but if the table does not exist,
# we need to set the field type.
if (append) {
if (!dbExistsTable(conn, name)) {
append <- FALSE
} else {
field.types <- NULL
}
}

dbWriteTable(conn, name, to_postgis(conn, value, binary),..., row.names = row.names,
overwrite = overwrite, append = append,
field.types = field.types)
}
)

to_postgis <- function(conn, x, binary) {
Expand Down
20 changes: 11 additions & 9 deletions man/dbWriteTable.Rd

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

9 changes: 9 additions & 0 deletions tests/testthat/test_postgis_RPostgres.R
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ test_that("can write to db", {
expect_silent(write_sf(pts, pg, "sf_meuse__", delete_layer = TRUE))
})

test_that("can create a missing table even if append is TRUE (#2206)", {
skip_if_not(can_con(pg), "could not connect to postgis database")
x <- st_sf(geometry = st_sfc(st_point(1:2)))
dbWriteTable(pg, "x", x, append = TRUE, temporary = TRUE)
col_type <- dbGetQuery(pg, "SELECT pg_typeof(geometry) as col_type FROM x")
expect_equal(unclass(col_type[["col_type"]]), "geometry")
dbExecute(pg, "drop table if exists x")
})

test_that("can handle multiple geom columns", {
skip_if_not(can_con(pg), "could not connect to postgis database")
multi <- cbind(pts[["geometry"]], st_transform(pts, 4326))
Expand Down

0 comments on commit ac0a1dd

Please sign in to comment.