From 52cf918a8dc836159a5d42ba8e9b3d3d39699192 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Fri, 29 Sep 2023 17:51:16 -0500 Subject: [PATCH 01/16] re-work alll database functions with separate connectors --- R/{import_from_FRED.R => db_FRED.R} | 111 +++++++++++---- R/{import_from_emissions.R => db_emissions.R} | 73 ++++++++-- R/db_gis.R | 127 ++++++++++++++++++ R/import_from_gis.R | 87 ------------ R/utils.R | 16 +-- ...{import_from_emissions.Rd => emissions.Rd} | 39 +++++- man/{import_from_FRED.Rd => fred.Rd} | 71 ++++++++-- man/gis.Rd | 91 +++++++++++++ man/import_from_gis.Rd | 56 -------- ...test-import_from_FRED.R => test-db_FRED.R} | 2 +- ...t_from_emissions.R => test-db_emissions.R} | 23 ++++ .../{test-import_from_gis.R => test-db_gis.R} | 22 ++- 12 files changed, 510 insertions(+), 208 deletions(-) rename R/{import_from_FRED.R => db_FRED.R} (54%) rename R/{import_from_emissions.R => db_emissions.R} (75%) create mode 100644 R/db_gis.R delete mode 100644 R/import_from_gis.R rename man/{import_from_emissions.Rd => emissions.Rd} (71%) rename man/{import_from_FRED.Rd => fred.Rd} (50%) create mode 100644 man/gis.Rd delete mode 100644 man/import_from_gis.Rd rename tests/testthat/{test-import_from_FRED.R => test-db_FRED.R} (97%) rename tests/testthat/{test-import_from_emissions.R => test-db_emissions.R} (62%) rename tests/testthat/{test-import_from_gis.R => test-db_gis.R} (62%) diff --git a/R/import_from_FRED.R b/R/db_FRED.R similarity index 54% rename from R/import_from_FRED.R rename to R/db_FRED.R index 789dfc1..65f1664 100644 --- a/R/import_from_FRED.R +++ b/R/db_FRED.R @@ -1,7 +1,35 @@ -#' @title Import data table from FRED (main CD Research database) data stored +#' @title FRED +#' +#' @description +#' Functions for interacting with FRED, the main CD Research database, stored #' Azure SQL Server #' -#' @param table_name character, which table to pull. +#' @details +#' Both "FRED" and "fred" capitalization are supported. +#' +#' - `fred_connection()` creates an S4 Microsoft SQL Server object for FRED. +#' This function will *not* automatically close the connection, so take +#' care to use [DBI::dbDisconnect()] once you are done. +#' - `import_from_fred()` imports a given table from FRED. The connection will +#' be automatically closed after the table is imported. +#' +#' @note See `vignette("Options")` to review package options. +#' +#' You must be set up with the appropriate database drivers to use these functions. +#' +#' **Windows** users need ODBC with Microsoft SQL. Contact IS support for ODBC installation. +#' +#' **Mac** users need `unixodbc`, `freetds`, and properly configured `odbc.ini`. +#' +#' See instructions in the +#' [onboarding guide](https://furry-adventure-596f3adb.pages.github.io/database-connections.html) +#' and contact package maintainer for assistance. +#' These functions rely on `{rlang}` internal functions. +#' Further examples can be found in `vignette("Databases")`. +#' +#' @rdname fred +#' @family database functions +#' #' @param uid character, your network ID. #' Default is `getOption("councilR.uid")`. #' @param pwd character, your network password. @@ -10,44 +38,44 @@ #' @param prod logical, whether to pull from the test or production db. #' Default is `TRUE`. #' -#' -#' @note See `vignette("Options")` to review package options. -#' You must be set up with the appropriate database drivers to use this function. -#' **Windows** users need ODBC with Microsoft SQL. Contact IS support for ODBC installation. -#' **Mac** users need `unixodbc`, `freetds`, and properly configured `odbc.ini`. -#' See instructions in the -#' [onboarding guide](https://furry-adventure-596f3adb.pages.github.io/database-connections.html) -#' and contact package maintainer for assistance. -#' -#' This function relies on `[{rlang}]` internal functions. -#' -#' @return Requested table +#' @return `fred_connection()` - A S4 Microsoft SQL Server object #' @export #' #' @examples #' \dontrun{ #' library(councilR) +#' library(DBI) #' #' # set options if you haven't already #' options( #' councilR.uid = "mc\\you", #' councilR.pwd = "mypwd" #' ) +#' # create connection +#' conn <- FRED_connection(prod = FALSE) +#' +#' # pull table using SQL +#' DBI::dbGetQuery(conn, "SELECT * FROM GQ_UNIT WHERE UNIT_ZIP = 55104") #' +#' # disconnect +#' DBI::dbDisconnect(conn) +#' +#' # import a specific table, with no additional SQL logic #' import_from_FRED(table_name = "GQ_UNIT", prod = FALSE) #' } +#' #' @importFrom DBI dbCanConnect dbGetQuery dbConnect dbDisconnect #' @importFrom odbc odbc #' @importFrom utils osVersion #' @importFrom purrr map -import_from_FRED <- function(table_name, - uid = getOption("councilR.uid"), - pwd = getOption("councilR.pwd"), - db = "CD_RESEARCH_WEB", - prod = TRUE) { +FRED_connection <- function( + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + db = "CD_RESEARCH_WEB", + prod = TRUE) { # check input types purrr::map( - c(table_name, uid, pwd, db), + c(uid, pwd, db), rlang:::check_string ) purrr::map( @@ -87,7 +115,7 @@ import_from_FRED <- function(table_name, Pwd = pwd ) == FALSE) { - stop("Database failed to connect") + cli::cli_abort("Database failed to connect") } } else if (drv == "SQL Server") { if ( @@ -100,7 +128,7 @@ import_from_FRED <- function(table_name, Server = serv, Trusted_Connection = "yes" ) == FALSE) { - stop("Database failed to connect") + cli::cli_abort("Database failed to connect") } } @@ -126,6 +154,42 @@ import_from_FRED <- function(table_name, ) } + # return connection + return(conn) +} + +#' @rdname fred +#' @export +fred_connection <- FRED_connection + +#' +#' @param table_name character, which table to pull. +#' +#' @return `import_from_FRED()` - Requested table +#' @export +#' +#' @importFrom DBI dbGetQuery dbDisconnect +#' @rdname fred +import_from_FRED <- function(table_name, + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + db = "CD_RESEARCH_WEB", + prod = TRUE) { + # check input types + purrr::map( + c(table_name, uid, pwd, db), + rlang:::check_string + ) + purrr::map( + c(prod), + rlang:::check_bool + ) + + conn <- fred_connection(uid = uid, + pwd = pwd, + db = db, + prod = prod) + db_sp_table <- DBI::dbGetQuery( conn, paste0("SELECT * FROM ", table_name) @@ -138,7 +202,8 @@ import_from_FRED <- function(table_name, -#' @rdname import_from_FRED +#' @rdname fred #' @export import_from_fred <- import_from_FRED + diff --git a/R/import_from_emissions.R b/R/db_emissions.R similarity index 75% rename from R/import_from_emissions.R rename to R/db_emissions.R index 0ac6a21..bb5ee9d 100644 --- a/R/import_from_emissions.R +++ b/R/db_emissions.R @@ -14,19 +14,22 @@ #' To access Azure, your IP address must be approved. Contact Sean Molloy. #' #' @note See `vignette("Options")` to review package options. -#' You must be set up with the appropriate database drivers to use this function. +#' You must be set up with the appropriate database drivers to use these functions. #' **Windows** users need ODBC with Microsoft SQL. Contact IS support for ODBC installation. #' **Mac** users need `unixodbc` and `freetds`. See instructions in the #' [onboarding guide](https://furry-adventure-596f3adb.pages.github.io/database-connections.html) #' -#' This function relies on `[{rlang}]` internal functions. +#' These functions rely on `[{rlang}]` internal functions. #' #' @return Requested table #' @export +#' @family database functions +#' @rdname emissions #' #' @examples #' \dontrun{ #' library(councilR) +#' library(DBI) #' #' # set options if you haven't already #' options( @@ -34,6 +37,16 @@ #' councilR.pwd = "mypwd" #' ) #' +#' # create connection +#' conn <- emissions_connect() +#' +#' # pull table using SQL +#' DBI::dbGetQuery(conn, "SELECT * FROM metro_energy.vw_electricity_residential_ctu") +#' +#' # disconnect +#' DBI::dbDisconnect(conn) +#' +#' # get specific tables #' t_electricity_residential_ctu <- import_from_emissions( #' table_name = "metro_energy.vw_electricity_residential_ctu" #' ) @@ -44,19 +57,18 @@ #' table_name = "metro_energy.vw_utility_natural_gas_by_ctu" #' ) #' } -#' @importFrom DBI dbCanConnect dbGetQuery dbConnect dbDisconnect +#' @importFrom DBI dbCanConnect dbConnect #' @importFrom odbc odbc #' @importFrom utils osVersion #' @importFrom purrr map -import_from_emissions <- function(table_name, - uid = getOption("councilR.uid"), - pwd = getOption("councilR.pwd"), - local = TRUE, - db = "CD_Emissions") { - requireNamespace("rlang", quietly = TRUE) +emissions_connection <- function( + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + local = TRUE, + db = "CD_Emissions") { # check input types purrr::map( - c(table_name, uid, pwd, db), + c(uid, pwd, db), rlang:::check_string ) purrr::map( @@ -90,7 +102,7 @@ import_from_emissions <- function(table_name, Pwd = pwd, Server = serv ) == FALSE) { - stop("Database failed to connect") + cli::cli_abort("Database failed to connect") } } else if (drv == "SQL Server") { if ( @@ -103,12 +115,10 @@ import_from_emissions <- function(table_name, Server = serv, Trusted_Connection = "yes" ) == FALSE) { - stop("Database failed to connect") + cli::cli_abort("Database failed to connect") } } - - conn <- if (drv == "FreeTDS") { DBI::dbConnect( @@ -131,6 +141,41 @@ import_from_emissions <- function(table_name, ) } + return(conn) +} + + +#' @param table_name character, which table to pull. +#' +#' @return `import_from_emissions()` - Requested table +#' @export +#' +#' @importFrom DBI dbGetQuery dbDisconnect +#' @importFrom purrr map +#' @rdname emissions +import_from_emissions <- function(table_name, + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + local = TRUE, + db = "CD_Emissions") { + # check input types + purrr::map( + c(table_name, uid, pwd, db), + rlang:::check_string + ) + purrr::map( + c(local), + rlang:::check_bool + ) + + + conn <- emissions_connection( + uid = uid, + pwd = pwd, + local = local, + db = db + ) + db_sp_table <- DBI::dbGetQuery( conn, paste0("SELECT * FROM ", table_name) diff --git a/R/db_gis.R b/R/db_gis.R new file mode 100644 index 0000000..0670c3b --- /dev/null +++ b/R/db_gis.R @@ -0,0 +1,127 @@ +#' @title GISLibrary +#' +#' @description +#' Functions for interacting with GISLibrary, the primary Met Council +#' ESRI geospatial database. +#' +#' @details +#' +#' - `gis_connection()` creates an S4 Microsoft SQL Server object for GISLibrary. +#' This function will *not* automatically close the connection, so take +#' care to use [DBI::dbDisconnect()] once you are done. +#' - `import_from_gis()` imports a given table from GISLibrary and +#' converts it into a [sf::sf()] object. The connection will +#' be automatically closed after the table is imported. +#' +#' Further examples can be found in `vignette("Databases", package = "councilR")`. +#' +#' @rdname gis +#' @family database functions +#' +#' @param dbname character, database name. Default is `"GISLibrary"`. +#' @param uid character, user ID. Default is `getOption("councilR.uid")` +#' @param pwd character, user password. Default is `getOption("councilR.pwd")`. +#' +#' +#' @examples \dontrun{ +#' library(councilR) +#' library(DBI) +#' library(sf) +#' +#' # set options if you haven't already +#' options( +#' councilR.uid = "mc\\uid", +#' councilR.pwd = "mypwd" +#' ) +#' +#' # create connection +#' gis <- gis_connection() +#' +#' # pull table using SQL and convert to sf +#' DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRPORTS where APNAME ='Flying Cloud'") %>% +#' st_as_sf(wkt = "wkt", crs = 26915) +#' +#' # disconnect +#' DBI::dbDisconnect(gis) +#' +#' # import a specific table, with no additional SQL logic +#' import_from_gis(query = "GISLibrary.dbo.AIRPORTS", dbname = "GISLibrary") +#' } +#' +#' +#' @return `gis_connection()` - A S4 Microsoft SQL Server object +#' +#' @family database functions +#' @importFrom DBI dbCanConnect dbConnect +#' @importFrom purrr map +#' @importFrom cli cli_abort +#' @importFrom odbc odbc +gis_connection <- function(dbname = "GISLibrary", + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd")){ + purrr::map( + c(dbname, uid, pwd), + rlang:::check_string + ) + + if (DBI::dbCanConnect( + odbc::odbc(), + dbname, + timeout = 10, + Uid = uid, + Pwd = pwd + ) != TRUE) { + cli::cli_abort("Database could not connect.") + } + + conn <- DBI::dbConnect( + odbc::odbc(), + dbname, + timeout = 10, + Uid = uid, + Pwd = pwd + ) + + +} + +#' @param query character, string with the database connection and feature class +#' @param .quiet logical, whether to print time elapsed message. +#' +#' @rdname gis +#' +#' @return `import_from_gis()` - A [sf::sf()] object +#' @export +#' @importFrom sf st_as_sf +#' @importFrom DBI dbGetQuery dbDisconnect +#' @importFrom tictoc tic toc +import_from_gis <- function(query, + dbname = "GISLibrary", + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + .quiet = FALSE) { + + if (.quiet == FALSE) { + tictoc::tic() + } + + conn <- gis_connection(dbname = dbname, + uid = uid, + pwd = pwd) + + que <- DBI::dbGetQuery( + conn, + paste0("SELECT *, Shape.STAsText() as wkt FROM ", query) + ) + + sf_df <- sf::st_as_sf( + que, + wkt = "wkt", crs = 26915 + ) + + DBI::dbDisconnect(conn) + + tictoc::toc() + + return(sf_df) +} diff --git a/R/import_from_gis.R b/R/import_from_gis.R deleted file mode 100644 index 8221331..0000000 --- a/R/import_from_gis.R +++ /dev/null @@ -1,87 +0,0 @@ -#' Import a dataset from ArcCatalog -#' -#' @param query character, string with the database connection and feature class -#' @param dbname character, database name. Default is `"GISLibrary"`. -#' Must match the database name in `query`. -#' @param uid character, user ID. Default is `getOption("councilR.uid")` -#' @param pwd character, user password. Default is `getOption("councilR.pwd")`. -#' @param .quiet logical, whether to print time elapsed message. -#' -#' @note See `vignette("Options")` to review package options. -#' You must be set up with the appropriate database drivers to use this function. -#' **Windows** users need ODBC with Microsoft SQL. Contact IS support for ODBC installation. -#' **Mac** users need `unixodbc`, `freetds`, and properly configured `odbc.ini`. -#' See instructions in the -#' [onboarding guide](https://furry-adventure-596f3adb.pages.github.io/database-connections.html) -#' and contact package maintainer for assistance. -#' -#' This function relies on `[{rlang}]` internal functions. -#' -#' @return An [`sf`] object -#' @export -#' @examples \dontrun{ -#' library(councilR) -#' -#' options( -#' councilR.uid = "mc\\uid", -#' councilR.pwd = "mypwd" -#' ) -#' -#' # query db name matches -#' import_from_gis(query = "GISLibrary.dbo.AIRPORTS", dbname = "GISLibrary") -#' } -#' @importFrom sf st_as_sf -#' @importFrom odbc odbc -#' @importFrom DBI dbGetQuery dbDisconnect dbCanConnect dbConnect -#' @importFrom tictoc tic toc -#' @importFrom purrr map -import_from_gis <- function(query, - dbname = "GISLibrary", - uid = getOption("councilR.uid"), - pwd = getOption("councilR.pwd"), - .quiet = FALSE) { - requireNamespace("rlang", quietly = TRUE) - - purrr::map( - c(query, dbname, uid, pwd), - rlang:::check_string - ) - - if (.quiet == FALSE) { - tictoc::tic() - } - - if (DBI::dbCanConnect( - odbc::odbc(), - dbname, - timeout = 10, - Uid = uid, - Pwd = pwd - ) != TRUE) { - stop("Database could not connect.") - } - - conn <- DBI::dbConnect( - odbc::odbc(), - dbname, - timeout = 10, - Uid = uid, - Pwd = pwd - ) - - que <- DBI::dbGetQuery( - conn, - paste0("SELECT *, Shape.STAsText() as wkt FROM ", query) - ) - - - sf_df <- sf::st_as_sf( - que, - wkt = "wkt", crs = 26915 - ) - DBI::dbDisconnect(conn) - - tictoc::toc() - - return(sf_df) -} diff --git a/R/utils.R b/R/utils.R index 36379a8..b84e2a6 100644 --- a/R/utils.R +++ b/R/utils.R @@ -23,17 +23,17 @@ councilR_file <- function(...) { requires_pkg <- function(pkg) { calling_function <- deparse(sys.calls()[[sys.nframe() - 1]]) if (!requireNamespace(pkg, quietly = TRUE)) { - stop(glue("{calling_function} requires the `{pkg}` package"), call. = FALSE) + cli::cli_abort(glue("{calling_function} requires the `{pkg}` package"), call. = FALSE) } } requires_pkg_version <- function(pkg, version) { calling_function <- deparse(sys.calls()[[sys.nframe() - 1]]) tryCatch(requires_pkg(pkg), error = function(e) { - stop(glue("{calling_function} requires the `{pkg}` package"), call. = FALSE) + cli::cli_abort(glue("{calling_function} requires the `{pkg}` package"), call. = FALSE) }) if (utils::packageVersion(pkg) < package_version(version)) { - stop( + cli::cli_abort( glue("{calling_function} requires `{pkg}` version {version} or later."), call. = FALSE ) @@ -58,11 +58,11 @@ with_rstudio <- function(fn, ..., stopifnot = FALSE) { if (rstudioapi::hasFun(fn)) { rstudio_fun <- get(fn, asNamespace("rstudioapi")) tryCatch(do.call(rstudio_fun, list(...)), error = function(e) { - stop(glue("Error in rstudioapi::{fn}(): {e$message}"), call. = FALSE) + cli::cli_abort(glue("Error in rstudioapi::{fn}(): {e$message}"), call. = FALSE) }) } else { - if (stopifnot) { - stop(glue( + if (cli::cli_abortifnot) { + cli::cli_abort(glue( "Your version of RStudio does not support this function: {fn}" ), call. = FALSE) } @@ -71,8 +71,8 @@ with_rstudio <- function(fn, ..., stopifnot = FALSE) { has_rstudio <- function(fn, stopifnot = FALSE) { has <- rstudioapi::hasFun(fn) - if (!has && stopifnot) { - stop(glue( + if (!has && cli::cli_abortifnot) { + cli::cli_abort(glue( "Your version of RStudio does not support this function: {fn}" ), call. = FALSE) } diff --git a/man/import_from_emissions.Rd b/man/emissions.Rd similarity index 71% rename from man/import_from_emissions.Rd rename to man/emissions.Rd index 5b64918..6e77425 100644 --- a/man/import_from_emissions.Rd +++ b/man/emissions.Rd @@ -1,9 +1,17 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/import_from_emissions.R -\name{import_from_emissions} +% Please edit documentation in R/db_emissions.R +\name{emissions_connection} +\alias{emissions_connection} \alias{import_from_emissions} \title{Import data table from greenhouse gas emissions scenario planning database} \usage{ +emissions_connection( + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + local = TRUE, + db = "CD_Emissions" +) + import_from_emissions( table_name, uid = getOption("councilR.uid"), @@ -13,8 +21,6 @@ import_from_emissions( ) } \arguments{ -\item{table_name}{character, which table to pull.} - \item{uid}{character, your network ID. Default is \code{getOption("councilR.uid")}. If you are accessing Azure, this value should be your full email address.} @@ -26,9 +32,13 @@ Default is \code{getOption("councilR.pwd")}. For example, \code{"my_password"}} Default is \code{TRUE}.} \item{db}{character, database name. Default is \code{"CD_Emissions"}.} + +\item{table_name}{character, which table to pull.} } \value{ Requested table + +\code{import_from_emissions()} - Requested table } \description{ Import data table from greenhouse gas emissions scenario planning database @@ -38,17 +48,18 @@ To access Azure, your IP address must be approved. Contact Sean Molloy. } \note{ See \code{vignette("Options")} to review package options. -You must be set up with the appropriate database drivers to use this function. +You must be set up with the appropriate database drivers to use these functions. \strong{Windows} users need ODBC with Microsoft SQL. Contact IS support for ODBC installation. \strong{Mac} users need \code{unixodbc} and \code{freetds}. See instructions in the \href{https://furry-adventure-596f3adb.pages.github.io/database-connections.html}{onboarding guide} -\if{html}{\out{
}}\preformatted{This function relies on `[\{rlang\}]` internal functions. +\if{html}{\out{
}}\preformatted{These functions rely on `[\{rlang\}]` internal functions. }\if{html}{\out{
}} } \examples{ \dontrun{ library(councilR) +library(DBI) # set options if you haven't already options( @@ -56,6 +67,16 @@ options( councilR.pwd = "mypwd" ) +# create connection +conn <- emissions_connect() + +# pull table using SQL +DBI::dbGetQuery(conn, "SELECT * FROM metro_energy.vw_electricity_residential_ctu") + +# disconnect +DBI::dbDisconnect(conn) + +# get specific tables t_electricity_residential_ctu <- import_from_emissions( table_name = "metro_energy.vw_electricity_residential_ctu" ) @@ -66,3 +87,9 @@ t_eia_energy_consumption_state <- import_from_emissions( ) } } +\seealso{ +Other database functions: +\code{\link{FRED_connection}()}, +\code{\link{gis_connection}()} +} +\concept{database functions} diff --git a/man/import_from_FRED.Rd b/man/fred.Rd similarity index 50% rename from man/import_from_FRED.Rd rename to man/fred.Rd index ae66c55..0c7ffd7 100644 --- a/man/import_from_FRED.Rd +++ b/man/fred.Rd @@ -1,11 +1,26 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/import_from_FRED.R -\name{import_from_FRED} +% Please edit documentation in R/db_FRED.R +\name{FRED_connection} +\alias{FRED_connection} +\alias{fred_connection} \alias{import_from_FRED} \alias{import_from_fred} -\title{Import data table from FRED (main CD Research database) data stored -Azure SQL Server} +\title{FRED} \usage{ +FRED_connection( + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + db = "CD_RESEARCH_WEB", + prod = TRUE +) + +fred_connection( + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + db = "CD_RESEARCH_WEB", + prod = TRUE +) + import_from_FRED( table_name, uid = getOption("councilR.uid"), @@ -23,8 +38,6 @@ import_from_fred( ) } \arguments{ -\item{table_name}{character, which table to pull.} - \item{uid}{character, your network ID. Default is \code{getOption("councilR.uid")}.} @@ -35,36 +48,70 @@ Default is \code{getOption("councilR.pwd")}. For example, \code{"mypwd"}} \item{prod}{logical, whether to pull from the test or production db. Default is \code{TRUE}.} + +\item{table_name}{character, which table to pull.} } \value{ -Requested table +\code{fred_connection()} - A S4 Microsoft SQL Server object + +\code{import_from_FRED()} - Requested table } \description{ -Import data table from FRED (main CD Research database) data stored +Functions for interacting with FRED, the main CD Research database, stored Azure SQL Server } +\details{ +Both "FRED" and "fred" capitalization are supported. +\itemize{ +\item \code{fred_connection()} creates an S4 Microsoft SQL Server object for FRED. +This function will \emph{not} automatically close the connection, so take +care to use \code{\link[DBI:dbDisconnect]{DBI::dbDisconnect()}} once you are done. +\item \code{import_from_fred()} imports a given table from FRED. The connection will +be automatically closed after the table is imported. +} +} \note{ See \code{vignette("Options")} to review package options. -You must be set up with the appropriate database drivers to use this function. + +You must be set up with the appropriate database drivers to use these functions. + \strong{Windows} users need ODBC with Microsoft SQL. Contact IS support for ODBC installation. + \strong{Mac} users need \code{unixodbc}, \code{freetds}, and properly configured \code{odbc.ini}. + See instructions in the \href{https://furry-adventure-596f3adb.pages.github.io/database-connections.html}{onboarding guide} and contact package maintainer for assistance. - -\if{html}{\out{
}}\preformatted{This function relies on `[\{rlang\}]` internal functions. -}\if{html}{\out{
}} +These functions rely on \code{{rlang}} internal functions. +Further examples can be found in \code{vignette("Databases")}. } \examples{ \dontrun{ library(councilR) +library(DBI) # set options if you haven't already options( councilR.uid = "mc\\\\you", councilR.pwd = "mypwd" ) +# create connection +conn <- FRED_connection(prod = FALSE) + +# pull table using SQL +DBI::dbGetQuery(conn, "SELECT * FROM GQ_UNIT WHERE UNIT_ZIP = 55104") +# disconnect +DBI::dbDisconnect(conn) + +# import a specific table, with no additional SQL logic import_from_FRED(table_name = "GQ_UNIT", prod = FALSE) } + +} +\seealso{ +Other database functions: +\code{\link{emissions_connection}()}, +\code{\link{gis_connection}()} } +\concept{database functions} diff --git a/man/gis.Rd b/man/gis.Rd new file mode 100644 index 0000000..b44a491 --- /dev/null +++ b/man/gis.Rd @@ -0,0 +1,91 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/db_gis.R +\name{gis_connection} +\alias{gis_connection} +\alias{import_from_gis} +\title{GISLibrary} +\usage{ +gis_connection( + dbname = "GISLibrary", + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd") +) + +import_from_gis( + query, + dbname = "GISLibrary", + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + .quiet = FALSE +) +} +\arguments{ +\item{dbname}{character, database name. Default is \code{"GISLibrary"}.} + +\item{uid}{character, user ID. Default is \code{getOption("councilR.uid")}} + +\item{pwd}{character, user password. Default is \code{getOption("councilR.pwd")}.} + +\item{query}{character, string with the database connection and feature class} + +\item{.quiet}{logical, whether to print time elapsed message.} +} +\value{ +\code{gis_connection()} - A S4 Microsoft SQL Server object + +\code{import_from_gis()} - A \code{\link[sf:sf]{sf::sf()}} object +} +\description{ +Functions for interacting with GISLibrary, the primary Met Council +ESRI geospatial database. +} +\details{ +\itemize{ +\item \code{gis_connection()} creates an S4 Microsoft SQL Server object for GISLibrary. +This function will \emph{not} automatically close the connection, so take +care to use \code{\link[DBI:dbDisconnect]{DBI::dbDisconnect()}} once you are done. +\item \code{import_from_gis()} imports a given table from GISLibrary and +converts it into a \code{\link[sf:sf]{sf::sf()}} object. The connection will +be automatically closed after the table is imported. +} + +Further examples can be found in \code{vignette("Databases", package = "councilR")}. +} +\examples{ +\dontrun{ +library(councilR) +library(DBI) +library(sf) + +# set options if you haven't already +options( + councilR.uid = "mc\\\\uid", + councilR.pwd = "mypwd" +) + +# create connection +gis <- gis_connection() + +# pull table using SQL and convert to sf +DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRPORTS where APNAME ='Flying Cloud'") \%>\% +st_as_sf(wkt = "wkt", crs = 26915) + +# disconnect +DBI::dbDisconnect(gis) + +# import a specific table, with no additional SQL logic +import_from_gis(query = "GISLibrary.dbo.AIRPORTS", dbname = "GISLibrary") +} + + +} +\seealso{ +Other database functions: +\code{\link{FRED_connection}()}, +\code{\link{emissions_connection}()} + +Other database functions: +\code{\link{FRED_connection}()}, +\code{\link{emissions_connection}()} +} +\concept{database functions} diff --git a/man/import_from_gis.Rd b/man/import_from_gis.Rd deleted file mode 100644 index 1920879..0000000 --- a/man/import_from_gis.Rd +++ /dev/null @@ -1,56 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/import_from_gis.R -\name{import_from_gis} -\alias{import_from_gis} -\title{Import a dataset from ArcCatalog} -\usage{ -import_from_gis( - query, - dbname = "GISLibrary", - uid = getOption("councilR.uid"), - pwd = getOption("councilR.pwd"), - .quiet = FALSE -) -} -\arguments{ -\item{query}{character, string with the database connection and feature class} - -\item{dbname}{character, database name. Default is \code{"GISLibrary"}. -Must match the database name in \code{query}.} - -\item{uid}{character, user ID. Default is \code{getOption("councilR.uid")}} - -\item{pwd}{character, user password. Default is \code{getOption("councilR.pwd")}.} - -\item{.quiet}{logical, whether to print time elapsed message.} -} -\value{ -An \code{\link{sf}} object -} -\description{ -Import a dataset from ArcCatalog -} -\note{ -See \code{vignette("Options")} to review package options. -You must be set up with the appropriate database drivers to use this function. -\strong{Windows} users need ODBC with Microsoft SQL. Contact IS support for ODBC installation. -\strong{Mac} users need \code{unixodbc}, \code{freetds}, and properly configured \code{odbc.ini}. -See instructions in the -\href{https://furry-adventure-596f3adb.pages.github.io/database-connections.html}{onboarding guide} -and contact package maintainer for assistance. - -This function relies on \verb{[\{rlang\}]} internal functions. -} -\examples{ -\dontrun{ -library(councilR) - -options( - councilR.uid = "mc\\\\uid", - councilR.pwd = "mypwd" -) - -# query db name matches -import_from_gis(query = "GISLibrary.dbo.AIRPORTS", dbname = "GISLibrary") -} -} diff --git a/tests/testthat/test-import_from_FRED.R b/tests/testthat/test-db_FRED.R similarity index 97% rename from tests/testthat/test-import_from_FRED.R rename to tests/testthat/test-db_FRED.R index 8e2fabb..986a516 100644 --- a/tests/testthat/test-import_from_FRED.R +++ b/tests/testthat/test-db_FRED.R @@ -14,7 +14,7 @@ testthat::skip_if(httr2::secret_has_key("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins")) testthat::test_that("group quarters dataset", { gq <- import_from_FRED( table_name = "GQ_UNIT", - prod = FALSE, + prod = TRUE, uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY"), db = "CD_RESEARCH_WEB" diff --git a/tests/testthat/test-import_from_emissions.R b/tests/testthat/test-db_emissions.R similarity index 62% rename from tests/testthat/test-import_from_emissions.R rename to tests/testthat/test-db_emissions.R index aa0abab..5edcfbb 100644 --- a/tests/testthat/test-import_from_emissions.R +++ b/tests/testthat/test-db_emissions.R @@ -21,6 +21,29 @@ testthat::skip_if( testthat::skip_if(httr2::secret_has_key("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins")) + + +testthat::test_that("emissions connection returns connection object", { + + test_conn <- emissions_connection( + uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), + pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY") + ) + + testthat::expect_s4_class(test_conn, "Microsoft SQL Server") + + ctu_test <- DBI::dbGetQuery(test_conn, "SELECT * FROM metro_energy.vw_electricity_residential_ctu") + + testthat::expect_equal(nrow(ctu_test), 186) + + DBI::dbDisconnect(test_conn) + + +}) + + + + testthat::test_that("Residential electricity data is returned", { electric_residential <- import_from_emissions( uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), diff --git a/tests/testthat/test-import_from_gis.R b/tests/testthat/test-db_gis.R similarity index 62% rename from tests/testthat/test-import_from_gis.R rename to tests/testthat/test-db_gis.R index ea0b14c..bbae055 100644 --- a/tests/testthat/test-import_from_gis.R +++ b/tests/testthat/test-db_gis.R @@ -10,8 +10,28 @@ testthat::skip_if( testthat::skip_if(httr2::secret_has_key("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins")) -# test return object attributes +testthat::test_that("GIS connection returns connection object", { + + test_conn <- gis_connection( + uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), + pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY") + ) + + testthat::expect_s4_class(test_conn, "Microsoft SQL Server") + + airp_test <- DBI::dbGetQuery(test_conn, "SELECT * FROM AIRPORTS WHERE APNAME = 'Flying Cloud'") + + testthat::expect_equal(nrow(airp_test), 4) + + DBI::dbDisconnect(test_conn) + +}) + + + + +# test return object attributes testthat::test_that("airports spatial dataset", { airport <- import_from_gis( uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), From ad2f8156bb7bfaa39590026be920fb869f86ad34 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Fri, 29 Sep 2023 17:51:27 -0500 Subject: [PATCH 02/16] start databases vignette --- vignettes/Databases.Rmd | 74 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 vignettes/Databases.Rmd diff --git a/vignettes/Databases.Rmd b/vignettes/Databases.Rmd new file mode 100644 index 0000000..c935357 --- /dev/null +++ b/vignettes/Databases.Rmd @@ -0,0 +1,74 @@ +--- +title: "Databases" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Databases} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(councilR) +library(DBI) +``` + +See `r vignette("Options", package = "councilR")` to review package options that make these functions run more smoothly. + +## FRED + +FRED contains most of CD Research's data tables, including tables for regional parks use estimates, population estimates, group quarters, and much more. Once you have the connection, you can use SQL queries to fetch only the data you need. + +```{r} +fred <- fred_connection() + +DBI::dbIsValid(fred) +DBI::dbListTables(fred, )[1:20] + +head(DBI::dbGetQuery(fred, "SELECT * FROM GQ_UNIT WHERE UNIT_ZIP = 55104")) + +DBI::dbDisconnect(fred) +``` + + +If you know the name of the table you need, you can pull it directly with `import_from_fred()`. This uses SQL `SELECT * FROM ___`. + + +```{r} +head(import_from_FRED(table_name = "GQ_UNIT", prod = FALSE)) +``` + + +## GISLibrary + +```{r} +gis <- gis_connection() +DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRPORTS where APNAME ='Flying Cloud'") +DBI::dbDisconnect(gis) +``` + +```{r} +airport <- import_from_gis( + query = "GISLibrary.dbo.AIRPORTS", + .quiet = TRUE +) +``` + +## Emissions + +```{r} +emissions <- emissions_connection() +DBI::dbGetQuery(emissions, "SELECT * FROM metro_energy.vw_electricity_residential_ctu") +DBI::dbDisconnect(emissions) +``` + +```{r} +import_from_emissions("metro_energy.vw_electricity_residential_ctu") +``` + From 0d0249180670d2f24faf92999075bf836bf2107c Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Fri, 29 Sep 2023 17:51:34 -0500 Subject: [PATCH 03/16] use cli::cli_abort --- R/snippets.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/snippets.R b/R/snippets.R index 05335d0..584638f 100644 --- a/R/snippets.R +++ b/R/snippets.R @@ -108,7 +108,7 @@ snippets_warn_mask <- function(new, old = NULL, warn = FALSE) { } if (!identical(file_new, file_old)) { - stop("Not a good idea to compare different snippets") + cli::cli_abort("Not a good idea to compare different snippets") } snp <- From 77712ea1bd8ebd1aa2c6ed4fe4ab0e72f15daffa Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Fri, 29 Sep 2023 17:51:40 -0500 Subject: [PATCH 04/16] increment deps; build --- DESCRIPTION | 10 +++++----- NAMESPACE | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index b2e99b6..bb5de99 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -25,20 +25,20 @@ Imports: cli (>= 3.6.1), data.table (>= 1.14.8), DBI (>= 1.1.3), - dplyr (>= 1.1.2), + dplyr (>= 1.1.3), fs (>= 1.6.3), - ggplot2 (>= 3.4.2), - ggspatial (>= 1.1.8), + ggplot2 (>= 3.4.3), + ggspatial (>= 1.1.9), glue (>= 1.6.2), magrittr (>= 2.0.3), odbc (>= 1.3.5), plotly (>= 4.10.2), - purrr (>= 1.0.1), + purrr (>= 1.0.2), rlang (>= 1.1.1), rstudioapi (>= 0.15.0), sf (>= 1.0-14), tictoc (>= 1.2), - tigris (>= 2.0.3), + tigris (>= 2.0.4), utils Suggests: citr (>= 0.3.2), diff --git a/NAMESPACE b/NAMESPACE index 7f37eb8..16fa477 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,12 +1,15 @@ # Generated by roxygen2: do not edit by hand export("%>%") +export(FRED_connection) export(council.pal) export(council_layout) export(council_pal2) export(council_theme) +export(emissions_connection) export(fetch_county_geo) export(fetch_ctu_geo) +export(fred_connection) export(import_from_FRED) export(import_from_emissions) export(import_from_fred) From 156c986b76ad4aa0d72184b7b63ead8e2fe687ec Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 11:06:03 -0500 Subject: [PATCH 05/16] fix stopifnot --- R/utils.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/utils.R b/R/utils.R index b84e2a6..da02dd3 100644 --- a/R/utils.R +++ b/R/utils.R @@ -61,7 +61,7 @@ with_rstudio <- function(fn, ..., stopifnot = FALSE) { cli::cli_abort(glue("Error in rstudioapi::{fn}(): {e$message}"), call. = FALSE) }) } else { - if (cli::cli_abortifnot) { + if (stopifnot) { cli::cli_abort(glue( "Your version of RStudio does not support this function: {fn}" ), call. = FALSE) @@ -71,7 +71,7 @@ with_rstudio <- function(fn, ..., stopifnot = FALSE) { has_rstudio <- function(fn, stopifnot = FALSE) { has <- rstudioapi::hasFun(fn) - if (!has && cli::cli_abortifnot) { + if (!has && stopifnot) { cli::cli_abort(glue( "Your version of RStudio does not support this function: {fn}" ), call. = FALSE) From 90bf8cb0a5e77fe9c75f5044c777f6817bf09c55 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 11:09:14 -0500 Subject: [PATCH 06/16] eval = FALSE, write comments and code for vignette --- vignettes/Databases.Rmd | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/vignettes/Databases.Rmd b/vignettes/Databases.Rmd index c935357..f61de4c 100644 --- a/vignettes/Databases.Rmd +++ b/vignettes/Databases.Rmd @@ -10,7 +10,8 @@ vignette: > ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, - comment = "#>" + comment = "#>", + eval = FALSE ) ``` @@ -19,16 +20,17 @@ library(councilR) library(DBI) ``` -See `r vignette("Options", package = "councilR")` to review package options that make these functions run more smoothly. +Database connections are a critical part of the work we do at the Metropolitan Council. + +See `vignette("Options", package = "councilR")` to review package options that make these functions run more smoothly. All `uid` and `pwd` parameters are `getOption("councilR.uid")` and `getOption("councilR.pwd")`. ## FRED FRED contains most of CD Research's data tables, including tables for regional parks use estimates, population estimates, group quarters, and much more. Once you have the connection, you can use SQL queries to fetch only the data you need. -```{r} +```{r fred-sql} fred <- fred_connection() -DBI::dbIsValid(fred) DBI::dbListTables(fred, )[1:20] head(DBI::dbGetQuery(fred, "SELECT * FROM GQ_UNIT WHERE UNIT_ZIP = 55104")) @@ -40,20 +42,30 @@ DBI::dbDisconnect(fred) If you know the name of the table you need, you can pull it directly with `import_from_fred()`. This uses SQL `SELECT * FROM ___`. -```{r} +```{r fred-table} head(import_from_FRED(table_name = "GQ_UNIT", prod = FALSE)) ``` ## GISLibrary -```{r} +GISLibrary is an ESRI SQL database that contains essential geospatial datasets. + +Generally, if the Council has published a dataset on [Minnesota Geospatial Commons](https://gisdata.mn.gov/), it is available in GISLibrary. + +```{r gis-sql} +# create connection gis <- gis_connection() + +# fetch with SQL DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRPORTS where APNAME ='Flying Cloud'") + +# remember to disconnect! DBI::dbDisconnect(gis) ``` -```{r} +```{r gis-table} +# import a specific table as an sf object, with no additional SQL airport <- import_from_gis( query = "GISLibrary.dbo.AIRPORTS", .quiet = TRUE @@ -62,13 +74,21 @@ airport <- import_from_gis( ## Emissions -```{r} +The emissions database is used for GHG inventory and scenario planning projects. + +```{r emissions-sql} +# create connection emissions <- emissions_connection() + +# fetch with SQL DBI::dbGetQuery(emissions, "SELECT * FROM metro_energy.vw_electricity_residential_ctu") + +# remember to disconnect! DBI::dbDisconnect(emissions) ``` -```{r} +```{r emissions-table} +# import a specific table with no additional SWL import_from_emissions("metro_energy.vw_electricity_residential_ctu") ``` From a8a6208e28b14ec203e594c59b6597ef60c11314 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 11:58:31 -0500 Subject: [PATCH 07/16] Update documentation --- R/db_FRED.R | 21 +++++++++++---------- R/db_emissions.R | 14 +++++++++----- R/db_gis.R | 21 ++++++++++----------- R/fetch_county_geo.R | 2 +- R/import_from_gpkg.R | 9 +++++---- R/theme_council.R | 2 +- man/emissions.Rd | 10 +++++++--- man/fetch_county_geo.Rd | 2 +- man/gis.Rd | 3 +-- man/import_from_gpkg.Rd | 9 +++++---- man/theme_council.Rd | 2 +- 11 files changed, 52 insertions(+), 43 deletions(-) diff --git a/R/db_FRED.R b/R/db_FRED.R index 65f1664..ad08cd6 100644 --- a/R/db_FRED.R +++ b/R/db_FRED.R @@ -68,11 +68,12 @@ #' @importFrom odbc odbc #' @importFrom utils osVersion #' @importFrom purrr map +#' @importFrom cli cli_abort FRED_connection <- function( - uid = getOption("councilR.uid"), - pwd = getOption("councilR.pwd"), - db = "CD_RESEARCH_WEB", - prod = TRUE) { + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd"), + db = "CD_RESEARCH_WEB", + prod = TRUE) { # check input types purrr::map( c(uid, pwd, db), @@ -185,10 +186,12 @@ import_from_FRED <- function(table_name, rlang:::check_bool ) - conn <- fred_connection(uid = uid, - pwd = pwd, - db = db, - prod = prod) + conn <- fred_connection( + uid = uid, + pwd = pwd, + db = db, + prod = prod + ) db_sp_table <- DBI::dbGetQuery( conn, @@ -205,5 +208,3 @@ import_from_FRED <- function(table_name, #' @rdname fred #' @export import_from_fred <- import_from_FRED - - diff --git a/R/db_emissions.R b/R/db_emissions.R index bb5ee9d..36c516d 100644 --- a/R/db_emissions.R +++ b/R/db_emissions.R @@ -19,15 +19,15 @@ #' **Mac** users need `unixodbc` and `freetds`. See instructions in the #' [onboarding guide](https://furry-adventure-596f3adb.pages.github.io/database-connections.html) #' -#' These functions rely on `[{rlang}]` internal functions. +#' These functions rely on `{rlang}` internal functions. #' #' @return Requested table #' @export #' @family database functions #' @rdname emissions #' -#' @examples -#' \dontrun{ +#' @examples \dontrun{ +#' #' library(councilR) #' library(DBI) #' @@ -49,18 +49,22 @@ #' # get specific tables #' t_electricity_residential_ctu <- import_from_emissions( #' table_name = "metro_energy.vw_electricity_residential_ctu" -#' ) +#' ) +#' #' t_eia_energy_consumption_state <- import_from_emissions( #' table_name = "state_energy.eia_energy_consumption_state" -#' ) +#' ) +#' # t_utility_natural_gas_by_ctu <- import_from_emissions( #' table_name = "metro_energy.vw_utility_natural_gas_by_ctu" #' ) #' } +#' #' @importFrom DBI dbCanConnect dbConnect #' @importFrom odbc odbc #' @importFrom utils osVersion #' @importFrom purrr map +#' @importFrom cli cli_abort emissions_connection <- function( uid = getOption("councilR.uid"), pwd = getOption("councilR.pwd"), diff --git a/R/db_gis.R b/R/db_gis.R index 0670c3b..43899e2 100644 --- a/R/db_gis.R +++ b/R/db_gis.R @@ -39,7 +39,7 @@ #' #' # pull table using SQL and convert to sf #' DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRPORTS where APNAME ='Flying Cloud'") %>% -#' st_as_sf(wkt = "wkt", crs = 26915) +#' st_as_sf(wkt = "wkt", crs = 26915) #' #' # disconnect #' DBI::dbDisconnect(gis) @@ -48,7 +48,6 @@ #' import_from_gis(query = "GISLibrary.dbo.AIRPORTS", dbname = "GISLibrary") #' } #' -#' #' @return `gis_connection()` - A S4 Microsoft SQL Server object #' #' @family database functions @@ -56,9 +55,10 @@ #' @importFrom purrr map #' @importFrom cli cli_abort #' @importFrom odbc odbc -gis_connection <- function(dbname = "GISLibrary", - uid = getOption("councilR.uid"), - pwd = getOption("councilR.pwd")){ +gis_connection <- function( + dbname = "GISLibrary", + uid = getOption("councilR.uid"), + pwd = getOption("councilR.pwd")) { purrr::map( c(dbname, uid, pwd), rlang:::check_string @@ -81,8 +81,6 @@ gis_connection <- function(dbname = "GISLibrary", Uid = uid, Pwd = pwd ) - - } #' @param query character, string with the database connection and feature class @@ -100,14 +98,15 @@ import_from_gis <- function(query, uid = getOption("councilR.uid"), pwd = getOption("councilR.pwd"), .quiet = FALSE) { - if (.quiet == FALSE) { tictoc::tic() } - conn <- gis_connection(dbname = dbname, - uid = uid, - pwd = pwd) + conn <- gis_connection( + dbname = dbname, + uid = uid, + pwd = pwd + ) que <- DBI::dbGetQuery( conn, diff --git a/R/fetch_county_geo.R b/R/fetch_county_geo.R index 2aa2b50..db2089d 100644 --- a/R/fetch_county_geo.R +++ b/R/fetch_county_geo.R @@ -31,7 +31,7 @@ #' ) #' } #' -#' @note This function relies on `[{rlang}]` internal functions. +#' @note This function relies on `{rlang}` internal functions. #' #' @importFrom tigris counties #' @importFrom cli cli_abort diff --git a/R/import_from_gpkg.R b/R/import_from_gpkg.R index fb814a1..35a894b 100644 --- a/R/import_from_gpkg.R +++ b/R/import_from_gpkg.R @@ -11,13 +11,14 @@ #' Default is `FALSE`. #' @param .quiet logical, suppress messages. Default is `TRUE`. #' -#' @return an [`sf`] object +#' @return [sf::sf()] object #' @export #' -#' @description Particularly useful for importing data from Minnesota Geospatial Commons -#' when access to the internal GIS database is unavailable. +#' @description This function is particularly useful for importing data from +#' [Minnesota Geospatial Commons](https://gisdata.mn.gov/) +#' when access to GISLibrary is unavailable. #' -#' @note This function relies on `[{rlang}]` internal functions. +#' @note This function relies on `{rlang}` internal functions. #' #' @importFrom sf read_sf st_transform #' @importFrom fs file_delete diff --git a/R/theme_council.R b/R/theme_council.R index 09a605e..cfb8454 100644 --- a/R/theme_council.R +++ b/R/theme_council.R @@ -51,7 +51,7 @@ #' a pull request. #' #' -#' @note This function relies on `[{rlang}]` internal functions. +#' @note This function relies on `{rlang}` internal functions. #' Further examples in `vignette("Color")`. #' #' @examples diff --git a/man/emissions.Rd b/man/emissions.Rd index 6e77425..dc8f5fc 100644 --- a/man/emissions.Rd +++ b/man/emissions.Rd @@ -53,11 +53,12 @@ You must be set up with the appropriate database drivers to use these functions. \strong{Mac} users need \code{unixodbc} and \code{freetds}. See instructions in the \href{https://furry-adventure-596f3adb.pages.github.io/database-connections.html}{onboarding guide} -\if{html}{\out{
}}\preformatted{These functions rely on `[\{rlang\}]` internal functions. +\if{html}{\out{
}}\preformatted{These functions rely on `\{rlang\}` internal functions. }\if{html}{\out{
}} } \examples{ \dontrun{ + library(councilR) library(DBI) @@ -79,13 +80,16 @@ DBI::dbDisconnect(conn) # get specific tables t_electricity_residential_ctu <- import_from_emissions( table_name = "metro_energy.vw_electricity_residential_ctu" -) + ) + t_eia_energy_consumption_state <- import_from_emissions( table_name = "state_energy.eia_energy_consumption_state" -) + ) + table_name = "metro_energy.vw_utility_natural_gas_by_ctu" ) } + } \seealso{ Other database functions: diff --git a/man/fetch_county_geo.Rd b/man/fetch_county_geo.Rd index 2e863e2..f14f94a 100644 --- a/man/fetch_county_geo.Rd +++ b/man/fetch_county_geo.Rd @@ -24,7 +24,7 @@ The default \code{fetch_county_geo()} to return county outlines, plus a suite of To get city, township, and unorganized territory (CTU) boundaries, use \code{fetch_ctu_geo()}. } \note{ -This function relies on \verb{[\{rlang\}]} internal functions. +This function relies on \code{{rlang}} internal functions. } \examples{ \dontrun{ diff --git a/man/gis.Rd b/man/gis.Rd index b44a491..f79a8e0 100644 --- a/man/gis.Rd +++ b/man/gis.Rd @@ -68,7 +68,7 @@ gis <- gis_connection() # pull table using SQL and convert to sf DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRPORTS where APNAME ='Flying Cloud'") \%>\% -st_as_sf(wkt = "wkt", crs = 26915) + st_as_sf(wkt = "wkt", crs = 26915) # disconnect DBI::dbDisconnect(gis) @@ -77,7 +77,6 @@ DBI::dbDisconnect(gis) import_from_gis(query = "GISLibrary.dbo.AIRPORTS", dbname = "GISLibrary") } - } \seealso{ Other database functions: diff --git a/man/import_from_gpkg.Rd b/man/import_from_gpkg.Rd index 842e52e..0fae0a8 100644 --- a/man/import_from_gpkg.Rd +++ b/man/import_from_gpkg.Rd @@ -31,14 +31,15 @@ Default is \code{FALSE}.} \item{.quiet}{logical, suppress messages. Default is \code{TRUE}.} } \value{ -an \code{\link{sf}} object +\code{\link[sf:sf]{sf::sf()}} object } \description{ -Particularly useful for importing data from Minnesota Geospatial Commons -when access to the internal GIS database is unavailable. +This function is particularly useful for importing data from +\href{https://gisdata.mn.gov/}{Minnesota Geospatial Commons} +when access to GISLibrary is unavailable. } \note{ -This function relies on \verb{[\{rlang\}]} internal functions. +This function relies on \code{{rlang}} internal functions. } \examples{ diff --git a/man/theme_council.Rd b/man/theme_council.Rd index 53fe084..fd5c33a 100644 --- a/man/theme_council.Rd +++ b/man/theme_council.Rd @@ -48,7 +48,7 @@ Please note that the y-axis text is horizontal, and long axis names will need to For example, consider using this piece of code: \code{labs(y = stringr::str_wrap("Axis labels are now horizontal, but you still need to insert some code to wrap long labels", width = 15))} } \note{ -This function relies on \verb{[\{rlang\}]} internal functions. +This function relies on \code{{rlang}} internal functions. Further examples in \code{vignette("Color")}. } \section{Council fonts}{ From e9199e7018f9f4789676f77ad698b47508e94f40 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 11:58:49 -0500 Subject: [PATCH 08/16] add alias, `import_gpkg()` --- R/import_from_gpkg.R | 4 ++++ man/import_from_gpkg.Rd | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/R/import_from_gpkg.R b/R/import_from_gpkg.R index 35a894b..d5b0877 100644 --- a/R/import_from_gpkg.R +++ b/R/import_from_gpkg.R @@ -78,3 +78,7 @@ import_from_gpkg <- function(link, return(out_sf) } + +#' @rdname import_from_gpkg +#' @export +import_gpkg <- import_from_gpkg diff --git a/man/import_from_gpkg.Rd b/man/import_from_gpkg.Rd index 0fae0a8..0b68484 100644 --- a/man/import_from_gpkg.Rd +++ b/man/import_from_gpkg.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/import_from_gpkg.R \name{import_from_gpkg} \alias{import_from_gpkg} +\alias{import_gpkg} \title{Import an \code{sf} object using a geopackage URL} \usage{ import_from_gpkg( @@ -12,6 +13,15 @@ import_from_gpkg( keep_temp = FALSE, .quiet = TRUE ) + +import_gpkg( + link, + save_file = FALSE, + save_path = getwd(), + .crs = 4326, + keep_temp = FALSE, + .quiet = TRUE +) } \arguments{ \item{link}{character, URL for the \code{.gpkg} object} From 3919d4bfe0818f988a76e38814794bab4b0bd360 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 11:58:57 -0500 Subject: [PATCH 09/16] add purrr example --- vignettes/Databases.Rmd | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/vignettes/Databases.Rmd b/vignettes/Databases.Rmd index f61de4c..55f5826 100644 --- a/vignettes/Databases.Rmd +++ b/vignettes/Databases.Rmd @@ -39,6 +39,34 @@ DBI::dbDisconnect(fred) ``` +The database connection is also useful if you want to pull multiple tables from a single connection with `{purrr}`. + +```{r fred-purrr} +library(purrr) +library(dplyr) + +fred <- fred_connection() + +park_tables <- purrr::map( + # park table names + list( + "PARK_UNIT", + "PARK_TYPE", + "PARK_IMPL_AGENCY" + ), + function(x) { + # for each table name, locate and collect data + dplyr::tbl(fred, x) %>% + dplyr::collect() + } +) + +park_tables + +DBI::dbDisconnect(fred) +``` + + If you know the name of the table you need, you can pull it directly with `import_from_fred()`. This uses SQL `SELECT * FROM ___`. @@ -57,7 +85,7 @@ Generally, if the Council has published a dataset on [Minnesota Geospatial Commo # create connection gis <- gis_connection() -# fetch with SQL +# fetch with SQL DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRPORTS where APNAME ='Flying Cloud'") # remember to disconnect! @@ -69,7 +97,7 @@ DBI::dbDisconnect(gis) airport <- import_from_gis( query = "GISLibrary.dbo.AIRPORTS", .quiet = TRUE -) +) ``` ## Emissions From 4197437e304b6870f1b2b13ba314ff673d6cd64a Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 11:59:26 -0500 Subject: [PATCH 10/16] re-work testing; add more tests --- NAMESPACE | 1 + tests/testthat/test-db_FRED.R | 61 +++++++++++++++++++++++++- tests/testthat/test-db_emissions.R | 4 -- tests/testthat/test-db_gis.R | 3 -- tests/testthat/test-import_from_gpkg.R | 16 ++++++- 5 files changed, 75 insertions(+), 10 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 16fa477..dc6ed93 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -15,6 +15,7 @@ export(import_from_emissions) export(import_from_fred) export(import_from_gis) export(import_from_gpkg) +export(import_gpkg) export(look) export(map_council_continuous) export(plotly_layout) diff --git a/tests/testthat/test-db_FRED.R b/tests/testthat/test-db_FRED.R index 986a516..58e8cdb 100644 --- a/tests/testthat/test-db_FRED.R +++ b/tests/testthat/test-db_FRED.R @@ -11,7 +11,7 @@ testthat::skip_if( testthat::skip_if(httr2::secret_has_key("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins")) -testthat::test_that("group quarters dataset", { +testthat::test_that("upercase group quarters table", { gq <- import_from_FRED( table_name = "GQ_UNIT", prod = TRUE, @@ -26,3 +26,62 @@ testthat::test_that("group quarters dataset", { # test that object returned is a data.frame testthat::expect_equal(class(gq)[[1]], "data.frame") }) + + +testthat::test_that("lowercase group quarters table", { + gq <- import_from_fred( + table_name = "GQ_UNIT", + prod = TRUE, + uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), + pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY"), + db = "CD_RESEARCH_WEB" + ) + + # test that data is returned from gq unit table, currently 11837 rows + testthat::expect_gte(nrow(gq), 11837) + + # test that object returned is a data.frame + testthat::expect_equal(class(gq)[[1]], "data.frame") +}) + + +testthat::test_that("lowercase park unit via SQL", { + fred <- fred_connection( + uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), + pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY"), + db = "CD_RESEARCH_WEB" + ) + + testthat::expect_s4_class(fred, "Microsoft SQL Server") + + park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM PARK_UNIT WHERE PARK_UNIT_ID_CURRENT = '094'") + + # test that data is returned from gq unit table, currently 11837 rows + testthat::expect_gte(nrow(park_unit), 1) + + # test that object returned is a data.frame + testthat::expect_equal(class(park_unit)[[1]], "data.frame") +}) + + + +testthat::test_that("uppercase park unit via SQL", { + fred <- FRED_connection( + uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), + pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY"), + db = "CD_RESEARCH_WEB" + ) + + + testthat::expect_s4_class(fred, "Microsoft SQL Server") + + park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM PARK_UNIT WHERE PARK_UNIT_ID_CURRENT = '094'") + + # test that data is returned from gq unit table, currently 11837 rows + testthat::expect_gte(nrow(park_unit), 1) + + # test that object returned is a data.frame + testthat::expect_equal(class(park_unit)[[1]], "data.frame") +}) + + diff --git a/tests/testthat/test-db_emissions.R b/tests/testthat/test-db_emissions.R index 5edcfbb..fb9e954 100644 --- a/tests/testthat/test-db_emissions.R +++ b/tests/testthat/test-db_emissions.R @@ -12,7 +12,6 @@ test_that("When local == FALSE, return an error message", { # skip on GH Actions testthat::skip_on_ci() -testthat::skip_on_cran() # skip if not connected to VPN testthat::skip_if( @@ -24,7 +23,6 @@ testthat::skip_if(httr2::secret_has_key("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins")) testthat::test_that("emissions connection returns connection object", { - test_conn <- emissions_connection( uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY") @@ -37,8 +35,6 @@ testthat::test_that("emissions connection returns connection object", { testthat::expect_equal(nrow(ctu_test), 186) DBI::dbDisconnect(test_conn) - - }) diff --git a/tests/testthat/test-db_gis.R b/tests/testthat/test-db_gis.R index bbae055..c481009 100644 --- a/tests/testthat/test-db_gis.R +++ b/tests/testthat/test-db_gis.R @@ -11,7 +11,6 @@ testthat::skip_if( testthat::skip_if(httr2::secret_has_key("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins")) testthat::test_that("GIS connection returns connection object", { - test_conn <- gis_connection( uid = httr2::secret_decrypt("QUHBRb_yoy2RRj59qno8NVXA7mW402xkins", "COUNCILR_KEY"), pwd = httr2::secret_decrypt("rQHk4S39pjfJ6yoKWUUNpQUDk2i9XA3d", "COUNCILR_KEY") @@ -24,8 +23,6 @@ testthat::test_that("GIS connection returns connection object", { testthat::expect_equal(nrow(airp_test), 4) DBI::dbDisconnect(test_conn) - - }) diff --git a/tests/testthat/test-import_from_gpkg.R b/tests/testthat/test-import_from_gpkg.R index e083f23..8a6a3cb 100644 --- a/tests/testthat/test-import_from_gpkg.R +++ b/tests/testthat/test-import_from_gpkg.R @@ -1,7 +1,19 @@ testthat::skip_if_offline() +testthat::test_that("metc districts with import from",{ + districts <- import_from_gpkg("https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/bdry_mcdistricts_2013/gpkg_bdry_mcdistricts_2013.zip") -testthat::expect_true(class(import_from_gpkg("https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/bdry_mcdistricts_2013/gpkg_bdry_mcdistricts_2013.zip"))[[1]] == "sf") + testthat::expect_s3_class(districts, "sf") + testthat::expect_equal(nrow(districts), 16) +}) -# testthat::expect_true(class(import_from_gpkg("https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/plan_parks_regional/gpkg_plan_parks_regional.zip"))[[1]] == "sf") + + +testthat::test_that("metc districts with import_gpkg",{ + districts <- import_gpkg("https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/bdry_mcdistricts_2013/gpkg_bdry_mcdistricts_2013.zip") + + testthat::expect_s3_class(districts, "sf") + + testthat::expect_equal(nrow(districts), 16) +}) From 7d559db989c37e6895693808d3b3c7ca591f44b8 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 11:59:50 -0500 Subject: [PATCH 11/16] style --- tests/testthat/test-db_FRED.R | 6 ++---- tests/testthat/test-import_from_gpkg.R | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/testthat/test-db_FRED.R b/tests/testthat/test-db_FRED.R index 58e8cdb..7be9a86 100644 --- a/tests/testthat/test-db_FRED.R +++ b/tests/testthat/test-db_FRED.R @@ -54,7 +54,7 @@ testthat::test_that("lowercase park unit via SQL", { testthat::expect_s4_class(fred, "Microsoft SQL Server") - park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM PARK_UNIT WHERE PARK_UNIT_ID_CURRENT = '094'") + park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM PARK_UNIT WHERE PARK_UNIT_ID_CURRENT = '094'") # test that data is returned from gq unit table, currently 11837 rows testthat::expect_gte(nrow(park_unit), 1) @@ -75,7 +75,7 @@ testthat::test_that("uppercase park unit via SQL", { testthat::expect_s4_class(fred, "Microsoft SQL Server") - park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM PARK_UNIT WHERE PARK_UNIT_ID_CURRENT = '094'") + park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM PARK_UNIT WHERE PARK_UNIT_ID_CURRENT = '094'") # test that data is returned from gq unit table, currently 11837 rows testthat::expect_gte(nrow(park_unit), 1) @@ -83,5 +83,3 @@ testthat::test_that("uppercase park unit via SQL", { # test that object returned is a data.frame testthat::expect_equal(class(park_unit)[[1]], "data.frame") }) - - diff --git a/tests/testthat/test-import_from_gpkg.R b/tests/testthat/test-import_from_gpkg.R index 8a6a3cb..dd0a3d9 100644 --- a/tests/testthat/test-import_from_gpkg.R +++ b/tests/testthat/test-import_from_gpkg.R @@ -1,6 +1,6 @@ testthat::skip_if_offline() -testthat::test_that("metc districts with import from",{ +testthat::test_that("metc districts with import from", { districts <- import_from_gpkg("https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/bdry_mcdistricts_2013/gpkg_bdry_mcdistricts_2013.zip") testthat::expect_s3_class(districts, "sf") @@ -10,7 +10,7 @@ testthat::test_that("metc districts with import from",{ -testthat::test_that("metc districts with import_gpkg",{ +testthat::test_that("metc districts with import_gpkg", { districts <- import_gpkg("https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/bdry_mcdistricts_2013/gpkg_bdry_mcdistricts_2013.zip") testthat::expect_s3_class(districts, "sf") From 135a1922bd81486b3c41e9481f6ce13a5ef21bc9 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 12:12:13 -0500 Subject: [PATCH 12/16] eval = FALSE --- vignettes/Databases.Rmd | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vignettes/Databases.Rmd b/vignettes/Databases.Rmd index 55f5826..3ced82a 100644 --- a/vignettes/Databases.Rmd +++ b/vignettes/Databases.Rmd @@ -17,7 +17,6 @@ knitr::opts_chunk$set( ```{r setup} library(councilR) -library(DBI) ``` Database connections are a critical part of the work we do at the Metropolitan Council. @@ -28,7 +27,8 @@ See `vignette("Options", package = "councilR")` to review package options that m FRED contains most of CD Research's data tables, including tables for regional parks use estimates, population estimates, group quarters, and much more. Once you have the connection, you can use SQL queries to fetch only the data you need. -```{r fred-sql} +```{r fred-sql, eval=FALSE} +library(DBI) fred <- fred_connection() DBI::dbListTables(fred, )[1:20] @@ -41,7 +41,7 @@ DBI::dbDisconnect(fred) The database connection is also useful if you want to pull multiple tables from a single connection with `{purrr}`. -```{r fred-purrr} +```{r fred-purrr, eval=FALSE} library(purrr) library(dplyr) @@ -70,7 +70,7 @@ DBI::dbDisconnect(fred) If you know the name of the table you need, you can pull it directly with `import_from_fred()`. This uses SQL `SELECT * FROM ___`. -```{r fred-table} +```{r fred-table, eval=FALSE} head(import_from_FRED(table_name = "GQ_UNIT", prod = FALSE)) ``` @@ -81,7 +81,7 @@ GISLibrary is an ESRI SQL database that contains essential geospatial datasets. Generally, if the Council has published a dataset on [Minnesota Geospatial Commons](https://gisdata.mn.gov/), it is available in GISLibrary. -```{r gis-sql} +```{r gis-sql, eval=FALSE} # create connection gis <- gis_connection() @@ -92,7 +92,7 @@ DBI::dbGetQuery(gis, "select *, Shape.STAsText() as wkt from GISLibrary.dbo.AIRP DBI::dbDisconnect(gis) ``` -```{r gis-table} +```{r gis-table, eval=FALSE} # import a specific table as an sf object, with no additional SQL airport <- import_from_gis( query = "GISLibrary.dbo.AIRPORTS", @@ -104,7 +104,7 @@ airport <- import_from_gis( The emissions database is used for GHG inventory and scenario planning projects. -```{r emissions-sql} +```{r emissions-sql, eval=FALSE} # create connection emissions <- emissions_connection() @@ -115,7 +115,7 @@ DBI::dbGetQuery(emissions, "SELECT * FROM metro_energy.vw_electricity_residentia DBI::dbDisconnect(emissions) ``` -```{r emissions-table} +```{r emissions-table, eval=FALSE} # import a specific table with no additional SWL import_from_emissions("metro_energy.vw_electricity_residential_ctu") ``` From 6e96058d7ac61842b346ebbfa1aea5cdf5995073 Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Mon, 2 Oct 2023 12:14:40 -0500 Subject: [PATCH 13/16] increment date and version --- DESCRIPTION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index bb5de99..a7f69bd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Type: Package Package: councilR Title: Functions and Templates for the Metropolitan Council -Version: 0.2.3 -Date: 2023-09-15 +Version: 0.2.4 +Date: 2023-10-05 Authors@R: c( person("Metropolitan Council", role = "cph"), person("Liz", "Roten", , "liz.roten@metc.state.mn.us", role = c("cre", "aut"), From 7f45d557d81cac0a21bb993490f067457acd7132 Mon Sep 17 00:00:00 2001 From: Laine McNamara <70707631+mcnamx@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:07:47 -0500 Subject: [PATCH 14/16] add Windows config for gis_connection --- R/db_gis.R | 69 +++++++++++++++++++++++------- tests/testthat/test-db_emissions.R | 2 +- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/R/db_gis.R b/R/db_gis.R index 43899e2..7686ea5 100644 --- a/R/db_gis.R +++ b/R/db_gis.R @@ -64,23 +64,62 @@ gis_connection <- function( rlang:::check_string ) - if (DBI::dbCanConnect( - odbc::odbc(), - dbname, - timeout = 10, - Uid = uid, - Pwd = pwd - ) != TRUE) { - cli::cli_abort("Database could not connect.") + serv <- "azdbsqlcl10.mc.local" + + # decide which driver to use based on OS + drv <- if (grepl("mac", osVersion)) { + "FreeTDS" + } else { + "SQL Server" } - conn <- DBI::dbConnect( - odbc::odbc(), - dbname, - timeout = 10, - Uid = uid, - Pwd = pwd - ) + # check that DB connection works + if (drv == "FreeTDS") { + if ( + DBI::dbCanConnect( + odbc::odbc(), + DSN = dbname, + Uid = uid, + Pwd = pwd + ) + == FALSE) { + cli::cli_abort("Database failed to connect") + } + } else if (drv == "SQL Server") { + if ( + DBI::dbCanConnect( + odbc::odbc(), + Driver = drv, + Database = dbname, + Uid = uid, + Pwd = pwd, + Server = serv, + Trusted_Connection = "yes" + ) == FALSE) { + cli::cli_abort("Database failed to connect") + } + } + + + conn <- + if (drv == "FreeTDS") { + DBI::dbConnect( + odbc::odbc(), + DSN = dbname, + Uid = uid, + Pwd = pwd + ) + } else if (drv == "SQL Server") { + DBI::dbConnect( + odbc::odbc(), + Driver = drv, + Database = dbname, + Uid = uid, + Pwd = pwd, + Server = serv, + Trusted_Connection = "yes" + ) + } } #' @param query character, string with the database connection and feature class diff --git a/tests/testthat/test-db_emissions.R b/tests/testthat/test-db_emissions.R index fb9e954..daa92aa 100644 --- a/tests/testthat/test-db_emissions.R +++ b/tests/testthat/test-db_emissions.R @@ -1,6 +1,6 @@ # basic testing -test_that("When local == FALSE, return an error message", { +testthat::test_that("When local == FALSE, return an error message", { testthat::expect_error( mod_2 <- import_from_emissions( local = FALSE, From 3f9c16b13eb9e45d53c7cbdfd39ef140b31fa111 Mon Sep 17 00:00:00 2001 From: Laine McNamara <70707631+mcnamx@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:27:26 -0500 Subject: [PATCH 15/16] change test FRED table avoid interim data type error on PARK_UNIT with "SQL Server" driver specifically --see https://github.com/r-dbi/odbc/issues/10 --- tests/testthat/test-db_FRED.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-db_FRED.R b/tests/testthat/test-db_FRED.R index 7be9a86..b9673b3 100644 --- a/tests/testthat/test-db_FRED.R +++ b/tests/testthat/test-db_FRED.R @@ -75,7 +75,7 @@ testthat::test_that("uppercase park unit via SQL", { testthat::expect_s4_class(fred, "Microsoft SQL Server") - park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM PARK_UNIT WHERE PARK_UNIT_ID_CURRENT = '094'") + park_unit <- DBI::dbGetQuery(fred, "SELECT * FROM MANUFACTURED_HOUSING_PARK WHERE PARK_ID_CURRENT = 23") # test that data is returned from gq unit table, currently 11837 rows testthat::expect_gte(nrow(park_unit), 1) From 584d2e95f9be05cbdd49327c529a9db52b982b1c Mon Sep 17 00:00:00 2001 From: Liz Roten Date: Thu, 5 Oct 2023 10:43:10 -0500 Subject: [PATCH 16/16] try using conditional tigris_refresh option TRUE if on CI, FALSE otherwise --- tests/testthat/setup.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 5ad7f3c..ab94b5a 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -1,5 +1,5 @@ options( tigris_use_cache = TRUE, progress_bar = FALSE, - tigris_refresh = FALSE + tigris_refresh = ifelse(testthat:::on_ci(), TRUE, FALSE) )