Skip to content

Commit

Permalink
gpkg_table(), gpkg_table_pragma() updates; closes #2
Browse files Browse the repository at this point in the history
  • Loading branch information
brownag committed Apr 25, 2023
1 parent bb15d1c commit 734dc74
Show file tree
Hide file tree
Showing 13 changed files with 264 additions and 283 deletions.
14 changes: 6 additions & 8 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Generated by roxygen2: do not edit by hand

S3method(dplyr.frame,SQLiteConnection)
S3method(dplyr.frame,character)
S3method(dplyr.frame,geopackage)
S3method(geopackage,SQLiteConnection)
S3method(geopackage,character)
S3method(geopackage,geopackage)
Expand All @@ -14,17 +11,18 @@ S3method(gpkg_disconnect,SQLiteConnection)
S3method(gpkg_disconnect,geopackage)
S3method(gpkg_is_connected,geopackage)
S3method(gpkg_source,geopackage)
S3method(gpkg_table,default)
S3method(gpkg_table_pragma,SQLiteConnection)
S3method(gpkg_table_pragma,character)
S3method(gpkg_table_pragma,geopackage)
S3method(gpkg_tables,geopackage)
S3method(lazy.frame,SQLiteConnection)
S3method(lazy.frame,character)
S3method(lazy.frame,geopackage)
S3method(print,geopackage)
export(dplyr.frame)
export(geopackage)
export(gpkg_2d_gridded_coverage_ancillary)
export(gpkg_add_contents)
export(gpkg_add_metadata_extension)
export(gpkg_add_relatedtables_extension)
export(gpkg_collect)
export(gpkg_connect)
export(gpkg_contents)
export(gpkg_create_contents)
Expand All @@ -38,13 +36,13 @@ export(gpkg_read)
export(gpkg_remove_attributes)
export(gpkg_source)
export(gpkg_table)
export(gpkg_table_pragma)
export(gpkg_tables)
export(gpkg_tile_set_data_null)
export(gpkg_update_contents)
export(gpkg_validate)
export(gpkg_write)
export(gpkg_write_attributes)
export(lazy.frame)
importFrom(DBI,dbConnect)
importFrom(DBI,dbDisconnect)
importFrom(DBI,dbGetQuery)
Expand Down
2 changes: 2 additions & 0 deletions R/gpkg-execute.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#' @param ... Additional arguments to `RSQLite::dbExecute()`
#' @param silent Used to suppress error messages, passed to `try()`. Default: `FALSE`.
#' @return Invisible result of `RSQLite::dbExecute()`; or `try-error` on error.
#'
#' @export
#'
gpkg_execute <- function(x, statement, ..., silent = FALSE) {
con <- .gpkg_connection_from_x(x)
res <- try(RSQLite::dbExecute(con, statement, ...), silent = silent)
Expand Down
14 changes: 9 additions & 5 deletions R/gpkg-io.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ gpkg_read <- function(x, connect = FALSE, quiet = TRUE) {
contents <- gpkg_contents(x)
# read grids
if (!any(contents$data_type %in% c("attributes", "features"))) {
r <- terra::rast(xx)
# convert to list of single-layer SpatRaster
grids <- as.list(r)
# assign raster table names
names(grids) <- names(r)
r <- try(terra::rast(xx), silent = TRUE)
if (inherits(r, 'try-error')) {
grids <- list()
} else {
# convert to list of single-layer SpatRaster
grids <- as.list(r)
# assign raster table names
names(grids) <- names(r)
}
} else grids <- list()

# read vector layers (error if there aren't any)
Expand Down
118 changes: 0 additions & 118 deletions R/gpkg-lazy.frame.R

This file was deleted.

14 changes: 0 additions & 14 deletions R/gpkg-sqlite.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,3 @@
}
res
}

#' Get table from a GeoPackage by table name
#' @param x A a `geopackage` object, path to a GeoPackage or an `SQLiteConnection`
#' @param table_name character. table name
#' @param query_string logical. Return SQLite query rather than executing it? Default: `FALSE`
#' @return A data.frame
#' @export
gpkg_table <- function(x, table_name, query_string = FALSE) {
q <- sprintf("SELECT * FROM %s", table_name)
if (query_string) {
return(q)
}
gpkg_query(x, q)
}
138 changes: 138 additions & 0 deletions R/gpkg-table.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# lazy data.frame implementation for tables in a geopackage
#' @export
#' @rdname gpkg_table
gpkg_table_pragma <- function(x, table_name = NULL, ...)
UseMethod("gpkg_table_pragma", x)

#' @rdname gpkg_table
#' @export
gpkg_table_pragma.character <- function(x, table_name = NULL, ...) {
g <- geopackage(x, connect = TRUE)
res <- gpkg_table_pragma(g, table_name = table_name, ...)
gpkg_disconnect(g)
res
}

#' @rdname gpkg_table
#' @export
gpkg_table_pragma.SQLiteConnection <- function(x, table_name, ...) {
gpkg_table_pragma(geopackage(x), table_name, ...)
}

#' Lazy Access to Tables by Name
#'
#' `gpkg_table_pragma()`: Get information on a table in a GeoPackage (without returning the whole table).
#'
#' @param x A geopackage object or character path to GeoPackage
#' @param table_name One or more table names; for `gpkg_table_pragma()` if `table_name=NULL` returns a record for each table. `gpkg_table()` requires `table_name` be specified
#' @param collect Materialize a data.frame object in memory? Default: `FALSE` requires 'dbplyr' package. `TRUE` uses 'RSQLite'.
#' @param query_string logical. Return SQLite query rather than executing it? Default: `FALSE`
#' @param ... Additional arguments. In `gpkg_table()` arguments in `...` are passed to `dplyr::tbl()`. For `gpkg_table_pragma()`, `...` arguments are (currently) not used.
#' @export
#' @rdname gpkg_table
#' @importFrom DBI dbGetQuery dbDisconnect
gpkg_table_pragma.geopackage <- function(x, table_name = NULL, ...) {
con <- .gpkg_connection_from_x(x)
tbls <- gpkg_list_tables(con)
dsn <- gpkg_source(x)
if (is.null(table_name)) {
table_name <- tbls
}

if (!all(table_name %in% tbls)) stop("no table with name: '", paste0(table_name[!table_name %in% tbls], collapse = "', '"), "' in ", dsn)

res <- do.call('rbind', lapply(table_name, function(xx) {
data.frame(dsn = dsn,
table_name = xx,
n_row = DBI::dbGetQuery(con, paste("SELECT COUNT(*) AS nrow FROM", xx)[[1]]),
table_info = I(list(DBI::dbGetQuery(con, paste0(
"PRAGMA table_info(", xx, ")"
))))[[1]] #TODO: custom print method for PRAGMA table_info?
)
}))
if (attr(con, 'disconnect')) {
DBI::dbDisconnect(con)
}
attr(res, 'class') <- c("gpkg_table_pragma", "data.frame")
res
}

#' @export
#' @rdname gpkg_table
#' @examplesIf !inherits(try(requireNamespace("RSQLite", quietly = TRUE)), 'try-error') &&!inherits(try(requireNamespace("dbplyr", quietly = TRUE)), 'try-error') && !inherits(try(requireNamespace("terra", quietly = TRUE)), 'try-error')
#' @description `gpkg_table()`: access a specific table (by name) and get a "lazy" `tibble` object referencing that table
#' @examples
#'
#' tf <- tempfile(fileext = ".gpkg")
#'
#' r <- terra::rast(system.file("extdata", "dem.tif", package = "gpkg"))
#'
#' gpkg_write(r,
#' destfile = tf,
#' RASTER_TABLE = "DEM1",
#' FIELD_NAME = "Elevation")
#'
#' gpkg_write(r,
#' destfile = tf,
#' append = TRUE,
#' RASTER_TABLE = "DEM2",
#' FIELD_NAME = "Elevation")
#'
#' g <- geopackage(tf)
#'
#' # inspect gpkg_contents table
#' gpkg_table(g, "gpkg_contents")
#'
#' # materialize a data.frame from gpkg_2d_gridded_tile_ancillary
#' library(dplyr, warn.conflicts = FALSE)
#'
#' gpkg_table(g, "gpkg_2d_gridded_tile_ancillary") %>%
#' dplyr::filter(tpudt_name == "DEM2") %>%
#' dplyr::select(mean, std_dev) %>%
#' dplyr::collect()
gpkg_table <- function(x,
table_name,
collect = FALSE,
query_string = FALSE,
...)
UseMethod("gpkg_table", x)

#' @rdname gpkg_table
#' @export
gpkg_table.default <- function(x,
table_name,
collect = FALSE,
query_string = FALSE,
...) {

con <- .gpkg_connection_from_x(x)

if (isTRUE(collect) || isTRUE(query_string)) {

if (attr(con, 'disconnect')) {
on.exit(DBI::dbDisconnect(con))
}

q <- sprintf("SELECT * FROM %s", table_name)
if (query_string) {
return(q)
}

return(gpkg_query(con, q))
}

stopifnot(requireNamespace("dbplyr", quietly = TRUE))

tbls <- gpkg_list_tables(con)

if (missing(table_name) || length(table_name) == 0) stop("table name should be one of:", paste0(tbls, collapse = ", "), call = FALSE)

dplyr::tbl(con, table_name, ...)
}

#' @description `gpkg_collect()`: alias for `gpkg_table(..., collect=TRUE)`
#' @rdname gpkg_table
#' @export
gpkg_collect <- function(x, table_name, query_string = FALSE, ...) {
gpkg_table(x, table_name, ..., query_string = query_string, collect = TRUE)
}
Loading

0 comments on commit 734dc74

Please sign in to comment.