5
5
# ' and a [`dm`] object as its second argument.
6
6
# ' The latter is copied to the former.
7
7
# ' The default is to create temporary tables, set `temporary = FALSE` to create permanent tables.
8
- # ' Unless `set_key_constraints` is `FALSE`, primary key constraints are set on all databases,
8
+ # ' Unless `set_key_constraints` is `FALSE`, primary key, foreign key, and unique constraints are set on all databases,
9
9
# ' and in addition foreign key constraints are set on MSSQL and Postgres databases.
10
10
# '
11
- # ' @details
12
- # ' No tables will be overwritten; passing `overwrite = TRUE` to the function will give an error.
13
- # ' Types are determined separately for each table, setting the `types` argument will
14
- # ' also throw an error.
15
- # ' The arguments are included in the signature to avoid passing them via the
16
- # ' `...` ellipsis.
17
- # '
18
11
# ' @inheritParams dm_examine_constraints
19
12
# '
20
13
# ' @param dest An object of class `"src"` or `"DBIConnection"`.
21
14
# ' @param dm A `dm` object.
22
- # ' @param overwrite,types,indexes,unique_indexes Must remain `NULL`.
23
15
# ' @param set_key_constraints If `TRUE` will mirror `dm` primary and foreign key constraints on a database
24
16
# ' and create unique indexes.
25
17
# ' Set to `FALSE` if your data model currently does not satisfy primary or foreign key constraints.
26
- # ' @param unique_table_names Deprecated.
27
18
# ' @param temporary If `TRUE`, only temporary tables will be created.
28
19
# ' These tables will vanish when disconnecting from the database.
29
20
# ' @param schema Name of schema to copy the `dm` to.
30
- # ' If `schema` is provided, an error will be thrown if `temporary = FALSE` or
31
- # ' `table_names` is not `NULL`.
32
- # '
33
- # ' Not all DBMS are supported.
34
- # ' @param table_names Desired names for the tables on `dest`; the names within the `dm` remain unchanged.
35
- # ' Can be `NULL`, a named character vector, a function or a one-sided formula.
36
- # '
37
- # ' If left `NULL` (default), the names will be determined automatically depending on the `temporary` argument:
38
- # '
39
- # ' 1. `temporary = TRUE` (default): unique table names based on the names of the tables in the `dm` are created.
40
- # ' 1. `temporary = FALSE`: the table names in the `dm` are used as names for the tables on `dest`.
41
- # '
42
- # ' If a function or one-sided formula, `table_names` is converted to a function
43
- # ' using [rlang::as_function()].
44
- # ' This function is called with the unquoted table names of the `dm` object
45
- # ' as the only argument.
46
- # ' The output of this function is processed by [DBI::dbQuoteIdentifier()],
47
- # ' that result should be a vector of identifiers of the same length
48
- # ' as the original table names.
49
- # '
50
- # ' Use a variant of
51
- # ' `table_names = ~ DBI::SQL(paste0("schema_name", ".", .x))`
52
- # ' to specify the same schema for all tables.
53
- # ' Use `table_names = identity` with `temporary = TRUE`
54
- # ' to avoid giving temporary tables unique names.
55
- # '
56
- # ' If a named character vector,
57
- # ' the names of this vector need to correspond to the table names in the `dm`,
58
- # ' and its values are the desired names on `dest`.
59
- # ' The value is processed by [DBI::dbQuoteIdentifier()],
60
- # ' that result should be a vector of identifiers of the same length
61
- # ' as the original table names.
21
+ # ' If `schema` is provided, an error will be thrown if `temporary = FALSE` or
22
+ # ' `table_names` is not `NULL`.
62
23
# '
63
- # ' Use qualified names corresponding to your database's syntax
64
- # ' to specify e.g. database and schema for your tables.
65
- # ' @param copy_to,... Deprecated.
24
+ # ' Not all DBMS are supported.
25
+ # ' @inheritParams dm_sql
26
+ # ' @inheritParams rlang::args_dots_empty
27
+ # ' @param unique_table_names,copy_to Deprecated.
66
28
# '
67
29
# ' @family DB interaction functions
68
30
# '
@@ -94,10 +56,6 @@ copy_dm_to <- function(
94
56
dest ,
95
57
dm ,
96
58
... ,
97
- types = NULL ,
98
- overwrite = NULL ,
99
- indexes = NULL ,
100
- unique_indexes = NULL ,
101
59
set_key_constraints = TRUE ,
102
60
unique_table_names = NULL ,
103
61
table_names = NULL ,
@@ -111,156 +69,134 @@ copy_dm_to <- function(
111
69
# 2. copy the tables to `dest`
112
70
# 3. implement the key situation within our `dm` on the DB
113
71
114
- if (! is_null(overwrite )) {
115
- abort_no_overwrite()
116
- }
117
-
118
- if (! is_null(types )) {
119
- abort_no_types()
120
- }
121
-
122
- if (! is_null(indexes )) {
123
- abort_no_indexes()
124
- }
125
-
126
- if (! is_null(unique_indexes )) {
127
- abort_no_unique_indexes()
128
- }
129
-
130
72
if (! is.null(unique_table_names )) {
131
- deprecate_soft (
73
+ deprecate_stop (
132
74
" 0.1.4" , " dm::copy_dm_to(unique_table_names = )" ,
133
- details = " Use `table_names = identity ` to use unchanged names for temporary tables."
75
+ details = " Use `table_names = set_names(names(dm)) ` to use unchanged names for temporary tables."
134
76
)
135
-
136
- if (is.null(table_names ) && temporary && ! unique_table_names ) {
137
- table_names <- identity
138
- }
139
77
}
140
78
141
79
if (! is.null(copy_to )) {
142
- deprecate_soft (
80
+ deprecate_stop (
143
81
" 1.0.0" , " dm::copy_dm_to(copy_to = )" ,
144
- details = " Use `dm_ddl ()` for more control over the schema creation process."
82
+ details = " Use `dm_sql ()` for more control over the schema creation process."
145
83
)
146
84
}
147
85
148
- if (dots_n(... ) > 0 ) {
149
- deprecate_soft(
150
- " 1.0.0" , " dm::copy_dm_to(... = )" ,
151
- details = " Use `dm_ddl()` for more control over the schema creation process."
152
- )
153
- }
86
+ check_dots_empty()
87
+
88
+ check_not_zoomed(dm )
154
89
155
90
check_suggested(" dbplyr" , use = TRUE )
156
91
157
92
dest <- src_from_src_or_con(dest )
158
- src_names <- src_tbls_impl(dm )
159
93
160
- if (is_db(dest )) {
161
- dest_con <- con_from_src_or_con(dest )
162
-
163
- # in case `table_names` was chosen by the user, check if the input makes sense:
164
- # 1. is there one name per dm-table?
165
- # 2. are there any duplicated table names?
166
- # 3. is it a named character or ident_q vector with the correct names?
167
- if (is.null(table_names )) {
168
- table_names_out <- repair_table_names_for_db(src_names , temporary , dest_con , schema )
169
- # https://github.com/tidyverse/dbplyr/issues/487
170
- if (is_mssql(dest )) {
171
- temporary <- FALSE
172
- }
173
- } else {
174
- if (! is.null(schema )) abort_one_of_schema_table_names()
175
- if (is_function(table_names ) || is_bare_formula(table_names )) {
176
- table_name_fun <- as_function(table_names )
177
- table_names_out <- set_names(table_name_fun(src_names ), src_names )
178
- } else {
179
- table_names_out <- table_names
180
- }
181
- check_naming(names(table_names_out ), src_names )
182
-
183
- if (anyDuplicated(table_names_out )) {
184
- problem <- table_names_out [duplicated(table_names_out )][[1 ]]
185
- abort_copy_dm_to_table_names_duplicated(problem )
186
- }
187
-
188
- names(table_names_out ) <- src_names
189
- }
190
- } else {
191
- # FIXME: Other data sources than local and database possible
192
- deprecate_soft(
193
- " 0.1.6" , " dm::copy_dm_to(dest = 'must refer to a remote data source')" ,
94
+ if (! is_db(dest )) {
95
+ deprecate_stop(
96
+ " 0.1.6" , " dm::copy_dm_to(dest = 'must refer to a DBI connection')" ,
194
97
" dm::collect.dm()"
195
98
)
196
- table_names_out <- set_names(src_names )
197
99
}
198
100
199
- check_not_zoomed(dm )
101
+ src_names <- src_tbls_impl(dm )
102
+ dest_con <- con_from_src_or_con(dest )
103
+
104
+ # in case `table_names` was chosen by the user, check if the input makes sense:
105
+ # 1. is there one name per dm-table?
106
+ # 2. are there any duplicated table names?
107
+ # 3. is it a named character or ident_q vector with the correct names?
108
+ if (is.null(table_names )) {
109
+ table_names_out <- repair_table_names_for_db(src_names , temporary , dest_con , schema )
110
+ # https://github.com/tidyverse/dbplyr/issues/487
111
+ if (is_mssql(dest )) {
112
+ temporary <- FALSE
113
+ }
114
+ } else {
115
+ if (! is.null(schema )) abort_one_of_schema_table_names()
116
+ if (is_function(table_names ) || is_bare_formula(table_names )) {
117
+ table_name_fun <- as_function(table_names )
118
+ table_names_out <- set_names(table_name_fun(src_names ), src_names )
119
+ } else {
120
+ table_names_out <- table_names
121
+ }
122
+ check_naming(names(table_names_out ), src_names )
200
123
201
- # FIXME: if same_src(), can use compute() but need to set NOT NULL and other
202
- # constraints
124
+ if (anyDuplicated(table_names_out )) {
125
+ problem <- table_names_out [duplicated(table_names_out )][[1 ]]
126
+ abort_copy_dm_to_table_names_duplicated(problem )
127
+ }
203
128
204
- # Shortcut necessary to avoid copying into .GlobalEnv
205
- if (! is_db(dest )) {
206
- return (dm )
129
+ names(table_names_out ) <- src_names
130
+ }
131
+
132
+ table_names_out <- ddl_check_table_names(table_names_out , dm )
133
+
134
+ if (isTRUE(set_key_constraints )) {
135
+ dm_for_sql <- dm
136
+ } else {
137
+ def_no_keys <- dm_get_def(dm )
138
+ def_no_keys $ uks [] <- list (new_uk())
139
+ def_no_keys $ fks [] <- list (new_fk())
140
+ # Must keep primary keys
141
+ dm_for_sql <- dm_from_def(def_no_keys )
207
142
}
208
143
209
- queries <- build_copy_queries( dest_con , dm , set_key_constraints , temporary , table_names_out )
144
+ sql <- dm_sql( dm_for_sql , dest_con , table_names_out , temporary )
210
145
211
- ticker_create <- new_ticker(
146
+ # FIXME: Extract function
147
+ # FIXME: Make descriptions part of the dm_sql() output
148
+
149
+ pre <- unlist(sql $ pre )
150
+ load <- unlist(sql $ load )
151
+ post <- unlist(sql $ post )
152
+
153
+ ticker_pre <- new_ticker(
212
154
" creating tables" ,
213
- n = length(queries $ sql_table ),
155
+ n = length(pre ),
214
156
progress = progress ,
215
157
top_level_fun = " copy_dm_to"
216
158
)
217
159
218
160
# create tables
219
- walk(queries $ sql_table , ticker_create (~ {
161
+ walk(pre , ticker_pre (~ {
220
162
DBI :: dbExecute(dest_con , .x , immediate = TRUE )
221
163
}))
222
164
223
- ticker_populate <- new_ticker(
165
+ ticker_load <- new_ticker(
224
166
" populating tables" ,
225
- n = length(queries $ name ),
167
+ n = length(load ),
226
168
progress = progress ,
227
169
top_level_fun = " copy_dm_to"
228
170
)
229
171
230
172
# populate tables
231
- pwalk(
232
- queries [c(" name" , " remote_name" )],
233
- ticker_populate(~ db_append_table(
234
- con = dest_con ,
235
- remote_table = .y ,
236
- table = dm [[.x ]],
237
- progress = progress ,
238
- autoinc = dm_get_all_pks(dm , table = !! .x )$ autoincrement
239
- ))
240
- )
173
+ walk(load , ticker_load(~ {
174
+ DBI :: dbExecute(dest_con , .x , immediate = TRUE )
175
+ }))
241
176
242
- ticker_index <- new_ticker(
177
+ ticker_post <- new_ticker(
243
178
" creating indexes" ,
244
- n = sum(lengths( queries $ sql_index ) ),
179
+ n = length( post ),
245
180
progress = progress ,
246
181
top_level_fun = " copy_dm_to"
247
182
)
248
183
249
184
# create indexes
250
- walk(unlist( queries $ sql_index ), ticker_index (~ {
185
+ walk(post , ticker_post (~ {
251
186
DBI :: dbExecute(dest_con , .x , immediate = TRUE )
252
187
}))
253
188
254
189
# remote dm is same as source dm with replaced data
190
+ # FIXME: Extract function
255
191
def <- dm_get_def(dm )
256
192
257
193
remote_tables <- map2(
258
194
table_names_out ,
259
195
map(def $ data , colnames ),
260
- ~ tbl(dest_con , ..1 , vars = ..2 )
196
+ ~ tbl(dest_con , .x , vars = .y )
261
197
)
262
198
263
- def $ data <- unname(remote_tables [names( dm )] )
199
+ def $ data <- unname(remote_tables )
264
200
remote_dm <- dm_from_def(def )
265
201
266
202
invisible (debug_dm_validate(remote_dm ))
0 commit comments