diff --git a/NAMESPACE b/NAMESPACE index 3a9b3d000..18de0b2a1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -32,6 +32,9 @@ S3method(cross_join,tbl_lazy) S3method(db_analyze,DBIConnection) S3method(db_col_types,DBIConnection) S3method(db_col_types,MariaDBConnection) +S3method(db_col_types,MySQL) +S3method(db_col_types,MySQLConnection) +S3method(db_col_types,PostgreSQL) S3method(db_col_types,PqConnection) S3method(db_col_types,TestConnection) S3method(db_collect,DBIConnection) diff --git a/R/backend-mysql.R b/R/backend-mysql.R index 82d5af960..045bc1cde 100644 --- a/R/backend-mysql.R +++ b/R/backend-mysql.R @@ -50,6 +50,17 @@ db_connection_describe.MySQL <- db_connection_describe.MariaDBConnection #' @export db_connection_describe.MySQLConnection <- db_connection_describe.MariaDBConnection +#' @export +db_col_types.MariaDBConnection <- function(con, table, call) { + table <- as_table_ident(table, error_call = call) + col_info_df <- DBI::dbGetQuery(con, glue_sql2(con, "SHOW COLUMNS FROM {.tbl table};")) + set_names(col_info_df[["Type"]], col_info_df[["Field"]]) +} +#' @export +db_col_types.MySQL <- db_col_types.MariaDBConnection +#' @export +db_col_types.MySQLConnection <- db_col_types.MariaDBConnection + #' @export sql_translation.MariaDBConnection <- function(con) { sql_variant( diff --git a/R/backend-postgres.R b/R/backend-postgres.R index 3cc32a92f..3ba4f05e4 100644 --- a/R/backend-postgres.R +++ b/R/backend-postgres.R @@ -404,4 +404,17 @@ db_supports_table_alias_with_as.PostgreSQL <- function(con) { TRUE } +#' @export +db_col_types.PqConnection <- function(con, table, call) { + table <- as_table_ident(table, error_call = call) + res <- DBI::dbSendQuery(con, glue_sql2(con, "SELECT * FROM {.tbl table} LIMIT 0")) + on.exit(DBI::dbClearResult(res)) + DBI::dbFetch(res, n = 0) + col_info_df <- DBI::dbColumnInfo(res) + set_names(col_info_df[[".typname"]], col_info_df[["name"]]) +} + +#' @export +db_col_types.PostgreSQL <- db_col_types.PqConnection + utils::globalVariables(c("strpos", "%::%", "%FROM%", "%ILIKE%", "DATE", "EXTRACT", "TO_CHAR", "string_agg", "%~*%", "%~%", "MONTH", "DOY", "DATE_TRUNC", "INTERVAL", "FLOOR", "WEEK")) diff --git a/R/db.R b/R/db.R index cf7512adf..90e8ad1c0 100644 --- a/R/db.R +++ b/R/db.R @@ -7,6 +7,8 @@ #' * `dbplyr_edition()` declares which version of the dbplyr API you want. #' See below for more details. #' +#' * `db_col_types()` returns the column types of a table. +#' #' @section dbplyr 2.0.0: #' dbplyr 2.0.0 renamed a number of generics so that they could be cleanly moved #' from dplyr to dbplyr. If you have an existing backend, you'll need to rename @@ -80,6 +82,26 @@ db_sql_render.DBIConnection <- function(con, sql, ..., cte = FALSE, sql_options sql_render(sql, con = con, ..., sql_options = sql_options) } +#' @rdname db-misc +#' @export +db_col_types <- function(con, table, call) { + if (is_null(table)) { + return(NULL) + } + + UseMethod("db_col_types") +} + +#' @export +db_col_types.TestConnection <- function(con, table, call) { + NULL +} + +#' @export +db_col_types.DBIConnection <- function(con, table, call) { + NULL +} + #' Options for generating SQL #' #' @param cte If `FALSE`, the default, subqueries are used. If `TRUE` common diff --git a/R/rows.R b/R/rows.R index 8bdbca864..7b1b15f2f 100644 --- a/R/rows.R +++ b/R/rows.R @@ -758,42 +758,6 @@ rows_auto_copy <- function(x, y, copy, call = caller_env()) { auto_copy(x, y, copy = copy, types = x_types) } -#' @export -db_col_types <- function(con, table, call) { - if (is_null(table)) { - return(NULL) - } - - UseMethod("db_col_types") -} - -#' @export -db_col_types.TestConnection <- function(con, table, call) { - NULL -} - -#' @export -db_col_types.DBIConnection <- function(con, table, call) { - NULL -} - -#' @export -db_col_types.PqConnection <- function(con, table, call) { - table <- as_table_ident(table, error_call = call) - res <- DBI::dbSendQuery(con, glue_sql2(con, "SELECT * FROM {.tbl table} LIMIT 0")) - on.exit(DBI::dbClearResult(res)) - DBI::dbFetch(res, n = 0) - col_info_df <- DBI::dbColumnInfo(res) - set_names(col_info_df[[".typname"]], col_info_df[["name"]]) -} - -#' @export -db_col_types.MariaDBConnection <- function(con, table, call) { - table <- as_table_ident(table, error_call = call) - col_info_df <- DBI::dbGetQuery(con, glue_sql2(con, "SHOW COLUMNS FROM {.tbl table};")) - set_names(col_info_df[["Type"]], col_info_df[["Field"]]) -} - rows_get_or_execute <- function(x, sql, returning_cols, call = caller_env()) { con <- remote_con(x) msg <- "Can't modify database table {.val {remote_name(x)}}." diff --git a/man/db-misc.Rd b/man/db-misc.Rd index 0a76400a7..b2a10b497 100644 --- a/man/db-misc.Rd +++ b/man/db-misc.Rd @@ -4,6 +4,7 @@ \alias{db_connection_describe} \alias{sql_join_suffix} \alias{db_sql_render} +\alias{db_col_types} \alias{dbplyr_edition} \title{Miscellaneous database generics} \usage{ @@ -13,6 +14,8 @@ sql_join_suffix(con, suffix, ...) db_sql_render(con, sql, ..., cte = FALSE, sql_options = NULL) +db_col_types(con, table, call) + dbplyr_edition(con) } \description{ @@ -26,6 +29,7 @@ from. It should be a single line, and ideally less than 60 characters wide. \itemize{ \item \code{dbplyr_edition()} declares which version of the dbplyr API you want. See below for more details. +\item \code{db_col_types()} returns the column types of a table. } } \section{dbplyr 2.0.0}{