diff --git a/DESCRIPTION b/DESCRIPTION index 454d847..3301c2a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -28,5 +28,5 @@ Suggests: testthat, data.table, purrr -RoxygenNote: 7.1.1 +RoxygenNote: 7.3.1 VignetteBuilder: knitr diff --git a/R/downloadData.R b/R/downloadData.R index 0f764a2..c3c551c 100644 --- a/R/downloadData.R +++ b/R/downloadData.R @@ -83,7 +83,9 @@ bqr_extract_data <- function(projectId = bqr_get_global_project(), compression <- match.arg(compression) destinationFormat <- match.arg(destinationFormat) - + + labels <- check_labels(getOption("bigQueryR.labels")) + check_gcs_auth() stopifnot(inherits(projectId, "character"), @@ -126,7 +128,8 @@ bqr_extract_data <- function(projectId = bqr_get_global_project(), fieldDelimiter = fieldDelimiter, destinationFormat = destinationFormat, compression = compression - ) + ), + labels = labels ) ) diff --git a/R/options.R b/R/options.R index 9c3015d..df7f9f9 100644 --- a/R/options.R +++ b/R/options.R @@ -8,7 +8,8 @@ googleAuthR.webapp.client_id = "68483650948-sufabj4nq9h1hjofp03hcjhk4af93080.apps.googleusercontent.com", googleAuthR.webapp.client_secret = "0tWYjliwXD32XhvDJHTl4NgN ", googleAuthR.scopes.selected = c("https://www.googleapis.com/auth/cloud-platform"), - googleAuthR.batch_endpoint = "https://www.googleapis.com/batch/bigquery/v2" + googleAuthR.batch_endpoint = "https://www.googleapis.com/batch/bigquery/v2", + bigQueryR.labels = list() ) options(googleAuthR.httr_oauth_cache = "bq.oauth") diff --git a/R/query.R b/R/query.R index c43482b..d089ad3 100644 --- a/R/query.R +++ b/R/query.R @@ -3,6 +3,7 @@ #' @param projectId The BigQuery project ID #' @param datasetId A datasetId within projectId #' @param query BigQuery SQL. You can also supply a file location of your query ending with \code{.sql} +#' @param labels Labels to tag to job in list format. lower-case only. Default empty list #' @param maxResults Max number per page of results. Set total rows with LIMIT in your query. #' @param useLegacySql Whether the query you pass is legacy SQL or not. Default TRUE #' @param useQueryCache Whether to use the query cache. Default TRUE, set to FALSE for realtime queries. @@ -40,6 +41,8 @@ bqr_query <- function(projectId = bqr_get_global_project(), timeoutMs = 600*1000){ check_bq_auth() + labels <- check_labels(getOption("bigQueryR.labels")) + if(endsWith(query, ".sql")){ query <- readChar(query, nchars = file.info(query)$size) } @@ -50,6 +53,7 @@ bqr_query <- function(projectId = bqr_get_global_project(), body <- list( kind = "bigquery#queryRequest", query = query, + labels = labels, maxResults = maxResults, useLegacySql = useLegacySql, useQueryCache = useQueryCache, @@ -125,6 +129,7 @@ bqr_query <- function(projectId = bqr_get_global_project(), #' @param projectId projectId to be billed. #' @param datasetId datasetId of where query will execute. #' @param query The BigQuery query as a string. +#' @param labels Labels to tag to job in list format. lower-case only. Default empty list #' @param destinationTableId Id of table the results will be written to. #' @param writeDisposition Behaviour if destination table exists. See Details. #' @param useLegacySql Whether the query you pass is legacy SQL or not. Default TRUE @@ -210,6 +215,8 @@ bqr_query_asynch <- function(projectId = bqr_get_global_project(), writeDisposition <- match.arg(writeDisposition) + labels <- check_labels(getOption("bigQueryR.labels")) + check_bq_auth() ## make job job <- @@ -239,7 +246,8 @@ bqr_query_asynch <- function(projectId = bqr_get_global_project(), query = query, useLegacySql = useLegacySql, writeDisposition = writeDisposition - ) + ), + labels = labels ) ) diff --git a/R/tables.R b/R/tables.R index 22fb0c5..db85af7 100644 --- a/R/tables.R +++ b/R/tables.R @@ -27,6 +27,8 @@ bqr_copy_table <- function(source_tableid, createDisposition <- match.arg(createDisposition) writeDisposition <- match.arg(writeDisposition) + + labels <- check_labels(getOption("bigQueryR.labels")) assert_that( is.string(source_projectid), @@ -52,7 +54,8 @@ bqr_copy_table <- function(source_tableid, tableId = destination_tableid ), writeDisposition = writeDisposition - ) + ), + labels = labels ) ) @@ -413,7 +416,7 @@ Table <- function(tableId, encryptionConfiguration = NULL, expirationTime = NULL, friendlyName = NULL, - labels = NULL, + labels = NULL, materializedView = NULL, rangePartitioning = NULL, requirePartitionFilter = NULL, @@ -431,6 +434,8 @@ Table <- function(tableId, # is.flag(requirePartitionFilter) ) + labels <- if (!is.null(labels)) check_labels(labels) else check_labels(getOption("bigQueryR.labels")) + tt <- list( tableReference = list(projectId = projectId, datasetId = datasetId, @@ -460,4 +465,4 @@ is.table <- function(x){ as.table <- function(x){ structure(x, class = "gar_Table") -} \ No newline at end of file +} diff --git a/R/utilities.R b/R/utilities.R index 6987064..84e2c77 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -137,3 +137,33 @@ idempotency <- function(){ set.seed(Sys.time()) paste(sample(c(LETTERS, letters, 0:9), 15, TRUE),collapse="") } + +#' Labels validity check +#' +#' A check of labels type and format validity +#' +#' @return labels or NULL +#' @keywords internal +#' @noRd +check_labels <- function(labels) { + if (!is.list(labels)) { + warning(paste0("Labels need to be a dictionary list - setting labels to list()"), immediate. = TRUE) + return(NULL) + } + for (nm in names(labels)) { + if (!is.character(labels[[nm]]) || length(labels[[nm]]) != 1) { + warning(sprintf("Label '%s' must be a single string type - setting labels to list()", nm), immediate. = TRUE) + return(NULL) + } + if (nm != tolower(nm)) { + warning(sprintf("Label key '%s' must be lowercase - setting labels to list()", nm), immediate. = TRUE) + return(NULL) + } + if (labels[[nm]] != tolower(labels[[nm]])) { + warning(sprintf("Label value '%s' must be lowercase - setting labels to list()", labels[[nm]]), immediate. = TRUE) + return(NULL) + } + } + + return(labels) +} diff --git a/man/bigQueryR.Rd b/man/bigQueryR.Rd index 9f2370f..cef19b9 100644 --- a/man/bigQueryR.Rd +++ b/man/bigQueryR.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/bigQueryR.R \docType{package} \name{bigQueryR} +\alias{bigQueryR-package} \alias{bigQueryR} \title{bigQueryR} \description{ @@ -10,3 +11,12 @@ Provides an interface with Google BigQuery \seealso{ \url{https://cloud.google.com/bigquery/docs/reference/v2/?hl=en} } +\author{ +\strong{Maintainer}: Mark Edmondson \email{r@sunholo.com} + +Other contributors: +\itemize{ + \item Hadley Wickham \email{hadley@rstudio.com} [contributor] +} + +} diff --git a/man/bqr_query.Rd b/man/bqr_query.Rd index 13198e3..d5ebcdf 100644 --- a/man/bqr_query.Rd +++ b/man/bqr_query.Rd @@ -8,6 +8,7 @@ bqr_query( projectId = bqr_get_global_project(), datasetId = bqr_get_global_dataset(), query, + labels = list(), maxResults = 1000, useLegacySql = TRUE, useQueryCache = TRUE, @@ -22,6 +23,8 @@ bqr_query( \item{query}{BigQuery SQL. You can also supply a file location of your query ending with \code{.sql}} +\item{labels}{Labels to tag to job in list format. lower-case only. Default empty list} + \item{maxResults}{Max number per page of results. Set total rows with LIMIT in your query.} \item{useLegacySql}{Whether the query you pass is legacy SQL or not. Default TRUE} diff --git a/man/bqr_query_asynch.Rd b/man/bqr_query_asynch.Rd index 03804bf..80149c4 100644 --- a/man/bqr_query_asynch.Rd +++ b/man/bqr_query_asynch.Rd @@ -8,6 +8,7 @@ bqr_query_asynch( projectId = bqr_get_global_project(), datasetId = bqr_get_global_dataset(), query, + labels = list(), destinationTableId, useLegacySql = TRUE, writeDisposition = c("WRITE_EMPTY", "WRITE_TRUNCATE", "WRITE_APPEND") @@ -20,6 +21,8 @@ bqr_query_asynch( \item{query}{The BigQuery query as a string.} +\item{labels}{Labels to tag to job in list format. lower-case only. Default empty list} + \item{destinationTableId}{Id of table the results will be written to.} \item{useLegacySql}{Whether the query you pass is legacy SQL or not. Default TRUE}