Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for Redshift connections #2215

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion R/build_copy_queries.R
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ build_copy_queries <- function(dest, dm, set_key_constraints = TRUE, temporary =
pk_col <- pk_col[[1]]

# Postgres:
if (is_postgres(dest)) {
if (is_postgres(dest) || is_redshift(dest)) {
types[pk_col] <- "SERIAL"
}

Expand Down
19 changes: 17 additions & 2 deletions R/db-helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ is_postgres <- function(dest) {
))
}

is_redshift <- function(dest) {
inherits_any(dest, c(
"src_RedshiftConnection", "RedshiftConnection"
))
}

is_mariadb <- function(dest) {
inherits_any(
dest,
Expand Down Expand Up @@ -122,8 +128,8 @@ find_name_clashes <- function(old, new) {

#' @autoglobal
get_src_tbl_names <- function(src, schema = NULL, dbname = NULL, names = NULL) {
if (!is_mssql(src) && !is_postgres(src) && !is_mariadb(src)) {
warn_if_arg_not(schema, only_on = c("MSSQL", "Postgres", "MariaDB"))
if (!is_mssql(src) && !is_postgres(src) && !is_redshift(src) && !is_mariadb(src)) {
warn_if_arg_not(schema, only_on = c("MSSQL", "Postgres", "Redshift", "MariaDB"))
warn_if_arg_not(dbname, only_on = "MSSQL")
tables <- src_tbls(src)
out <- purrr::map(tables, ~ DBI::Id(table = .x))
Expand All @@ -148,6 +154,11 @@ get_src_tbl_names <- function(src, schema = NULL, dbname = NULL, names = NULL) {
schema <- schema_postgres(con, schema)
dbname <- warn_if_arg_not(dbname, only_on = "MSSQL")
names_table <- get_names_table_postgres(con)
} else if (is_redshift(src)) {
# Redshift
schema <- schema_redshift(con, schema)
dbname <- warn_if_arg_not(dbname, only_on = "MSSQL")
names_table <- get_names_table_redshift(con)
} else if (is_mariadb(src)) {
# MariaDB
schema <- schema_mariadb(con, schema)
Expand Down Expand Up @@ -224,6 +235,8 @@ schema_postgres <- function(con, schema) {
schema
}

schema_redshift <- schema_postgres

schema_mariadb <- function(con, schema) {
if (is_null(schema)) {
schema <- sql("database()")
Expand Down Expand Up @@ -262,4 +275,6 @@ get_names_table_postgres <- function(con) {
)
}

get_names_table_redshift <- get_names_table_postgres

get_names_table_mariadb <- get_names_table_postgres
4 changes: 2 additions & 2 deletions R/db-interface.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#' The latter is copied to the former.
#' The default is to create temporary tables, set `temporary = FALSE` to create permanent tables.
#' Unless `set_key_constraints` is `FALSE`, primary key constraints are set on all databases,
#' and in addition foreign key constraints are set on MSSQL and Postgres databases.
#' and in addition foreign key constraints are set on MSSQL and Postgres/Redshift databases.
#'
#' @inheritParams dm_examine_constraints
#'
Expand Down Expand Up @@ -280,7 +280,7 @@ db_append_table <- function(con, remote_table, table, progress, top_level_fun =
}
DBI::dbExecute(con, sql, immediate = TRUE)
}))
} else if (is_postgres(con)) {
} else if (is_postgres(con) || is_redshift(con)) {
# https://github.com/r-dbi/RPostgres/issues/384
table <- as.data.frame(table)
# https://github.com/r-dbi/RPostgres/issues/382
Expand Down
10 changes: 5 additions & 5 deletions R/dm_from_con.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' @description
#' `dm_from_con()` creates a [dm] from some or all tables in a [src]
#' (a database or an environment) or which are accessible via a DBI-Connection.
#' For Postgres and SQL Server databases, primary and foreign keys
#' For Postgres/Redshift and SQL Server databases, primary and foreign keys
#' are imported from the database.
#'
#' @param con A [`DBI::DBIConnection-class`] or a `Pool` object.
Expand All @@ -14,13 +14,13 @@
#'
#' Set to `TRUE` to query the definition of primary and
#' foreign keys from the database.
#' Currently works only for Postgres and SQL Server databases.
#' Currently works only for Postgres/Redshift and SQL Server databases.
#' The default attempts to query and issues an informative message.
#' @param .names
#' `r lifecycle::badge("experimental")`
#'
#' A glue specification that describes how to name the tables
#' within the output, currently only for MSSQL, Postgres and MySQL/MariaDB.
#' within the output, currently only for MSSQL, Postgres/Redshift and MySQL/MariaDB.
#' This can use `{.table}` to stand for the table name, and
#' `{.schema}` to stand for the name of the schema which the table lives
#' within. The default (`NULL`) is equivalent to `"{.table}"` when a single
Expand All @@ -30,11 +30,11 @@
#'
#' Additional parameters for the schema learning query.
#'
#' - `schema`: supported for MSSQL (default: `"dbo"`), Postgres (default: `"public"`), and MariaDB/MySQL
#' - `schema`: supported for MSSQL (default: `"dbo"`), Postgres/Redshift (default: `"public"`), and MariaDB/MySQL
#' (default: current database). Learn the tables in a specific schema (or database for MariaDB/MySQL).
#' - `dbname`: supported for MSSQL. Access different databases on the connected MSSQL-server;
#' default: active database.
#' - `table_type`: supported for Postgres (default: `"BASE TABLE"`). Specify the table type. Options are:
#' - `table_type`: supported for Postgres/Redshift (default: `"BASE TABLE"`). Specify the table type. Options are:
#' 1. `"BASE TABLE"` for a persistent table (normal table type)
#' 2. `"VIEW"` for a view
#' 3. `"FOREIGN TABLE"` for a foreign table
Expand Down
4 changes: 2 additions & 2 deletions R/dm_sql.R
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,8 @@ ddl_get_col_defs <- function(tables, con, table_names, pks) {
# extract column name representing primary key
pk_col_name <- pk_col$pk_col[[1]]

# Postgres:
if (is_postgres(con)) {
# Postgres/Redshift:
if (is_postgres(con) || is_redshift(con)) {
types[pk_col_name] <- "SERIAL"
}

Expand Down
2 changes: 1 addition & 1 deletion R/learn.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' @description If there are any permament tables on a DB, a new [`dm`] object can be created that contains those tables,
#' along with their primary and foreign key constraints.
#'
#' Currently this only works with MSSQL and Postgres databases.
#' Currently this only works with MSSQL and Postgres/Redshift databases.
#'
#' The default database schema will be used; it is currently not possible to parametrize the funcion with a specific database schema.
#'
Expand Down
11 changes: 10 additions & 1 deletion R/meta.R
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ dm_meta_raw <- function(con, catalog) {
if (is_mssql(src)) {
columns <- columns %>%
mutate(is_autoincrement = sql("CAST(COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') AS BIT)"))
} else if (is_postgres(src)) {
} else if (is_postgres(src) || is_redshift(src)) {
columns <- columns %>%
mutate(is_autoincrement = sql("CASE WHEN column_default IS NULL THEN FALSE ELSE column_default SIMILAR TO '%nextval%' END"))
} else if (is_mariadb(src)) {
Expand Down Expand Up @@ -134,6 +134,15 @@ dm_meta_raw <- function(con, catalog) {
"constraint_catalog", "constraint_schema", "constraint_name",
"ordinal_position"
))
} else if (is_redshift(src)) {
constraint_column_usage <-
tbl_lc(src, "information_schema.key_column_usage", vars = c(
"table_catalog",
"table_schema", "table_name", "column_name",
"constraint_catalog", "constraint_schema", "constraint_name",
"ordinal_position"
)) %>%
filter(!is.na(table_name))
} else if (is_mssql(src)) {
constraint_column_usage <- mssql_constraint_column_usage(src, table_constraints, catalog)
} else {
Expand Down
4 changes: 2 additions & 2 deletions R/schema.R
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ sql_schema_table_list_postgres <- function(con, schema = NULL) {
#'
#' @inheritParams db_schema_create
#' @param force Boolean, default `FALSE`. Set to `TRUE` to drop a schema and
#' all objects it contains at once. Currently only supported for Postgres.
#' all objects it contains at once. Currently only supported for Postgres/Redshift.
#'
#' @details Methods are not available for all DBMS.
#'
Expand Down Expand Up @@ -357,7 +357,7 @@ db_schema_drop.PqConnection <- function(con, schema, force = FALSE, ...) {
`db_schema_drop.Microsoft SQL Server` <- function(con, schema, force = FALSE, dbname = NULL, ...) {
warn_if_arg_not(
force,
only_on = "Postgres",
only_on = c("Postgres", "Redshift"),
correct = FALSE,
additional_msg = "Please remove potential objects from the schema manually."
)
Expand Down
2 changes: 1 addition & 1 deletion man/copy_dm_to.Rd

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

2 changes: 1 addition & 1 deletion man/db_schema_drop.Rd

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

10 changes: 5 additions & 5 deletions man/dm_from_con.Rd

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

6 changes: 3 additions & 3 deletions man/dm_from_src.Rd

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

2 changes: 1 addition & 1 deletion scratch/info.R
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ info_local <-
collect()

quote_fq_schema <- function(con, catalog, schema) {
if (is_postgres(con) || is_mssql(con)) {
if (is_postgres(con) || is_redshift(con) || is_mssql(con)) {
catalog <- dbQuoteIdentifier(con, catalog)
schema <- dbQuoteIdentifier(con, schema)
paste0(catalog, ".", schema)
Expand Down
Loading