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,
9
- # ' and in addition foreign key constraints are set on MSSQL and Postgres databases.
8
+ # ' Unless `set_key_constraints` is `FALSE`, primary key, foreign key, and unique constraints
9
+ # ' are set on all databases.
10
10
# '
11
11
# ' @inheritParams dm_examine_constraints
12
12
# '
13
13
# ' @param dest An object of class `"src"` or `"DBIConnection"`.
14
14
# ' @param dm A `dm` object.
15
- # ' @inheritParams rlang::args_dots_empty
16
15
# ' @param set_key_constraints If `TRUE` will mirror `dm` primary and foreign key constraints on a database
17
16
# ' and create indexes for foreign key constraints.
18
17
# ' Set to `FALSE` if your data model currently does not satisfy primary or foreign key constraints.
23
22
# ' `table_names` is not `NULL`.
24
23
# '
25
24
# ' Not all DBMS are supported.
26
- # ' @param table_names Desired names for the tables on `dest`; the names within the `dm` remain unchanged.
27
- # ' Can be `NULL`, a named character vector, or a vector of [DBI::Id] objects.
28
- # '
29
- # ' If left `NULL` (default), the names will be determined automatically depending on the `temporary` argument:
30
- # '
31
- # ' 1. `temporary = TRUE` (default): unique table names based on the names of the tables in the `dm` are created.
32
- # ' 1. `temporary = FALSE`: the table names in the `dm` are used as names for the tables on `dest`.
33
- # '
34
- # ' If a function or one-sided formula, `table_names` is converted to a function
35
- # ' using [rlang::as_function()].
36
- # ' This function is called with the unquoted table names of the `dm` object
37
- # ' as the only argument.
38
- # ' The output of this function is processed by [DBI::dbQuoteIdentifier()],
39
- # ' that result should be a vector of identifiers of the same length
40
- # ' as the original table names.
41
- # '
42
- # ' Use a variant of
43
- # ' `table_names = ~ DBI::SQL(paste0("schema_name", ".", .x))`
44
- # ' to specify the same schema for all tables.
45
- # ' Use `table_names = identity` with `temporary = TRUE`
46
- # ' to avoid giving temporary tables unique names.
47
- # '
48
- # ' If a named character vector,
49
- # ' the names of this vector need to correspond to the table names in the `dm`,
50
- # ' and its values are the desired names on `dest`.
51
- # ' The value is processed by [DBI::dbQuoteIdentifier()],
52
- # ' that result should be a vector of identifiers of the same length
53
- # ' as the original table names.
54
- # '
55
- # ' Use qualified names corresponding to your database's syntax
56
- # ' to specify e.g. database and schema for your tables.
57
- # ' @param unique_table_names,copy_to Must be `NULL`.
25
+ # ' @inheritParams dm_sql
26
+ # ' @inheritParams rlang::args_dots_empty
27
+ # ' @param unique_table_names,copy_to Deprecated.
58
28
# '
59
29
# ' @family DB interaction functions
60
30
# '
@@ -100,14 +70,10 @@ copy_dm_to <- function(
100
70
# 3. implement the key situation within our `dm` on the DB
101
71
102
72
if (! is.null(unique_table_names )) {
103
- deprecate_warn (
73
+ deprecate_stop (
104
74
" 0.1.4" , " dm::copy_dm_to(unique_table_names = )" ,
105
- 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."
106
76
)
107
-
108
- if (is.null(table_names ) && temporary && ! unique_table_names ) {
109
- table_names <- identity
110
- }
111
77
}
112
78
113
79
if (! is.null(copy_to )) {
@@ -124,110 +90,113 @@ copy_dm_to <- function(
124
90
check_suggested(" dbplyr" , " copy_dm_to" )
125
91
126
92
dest <- src_from_src_or_con(dest )
127
- src_names <- src_tbls_impl(dm )
128
93
129
- if (is_db(dest )) {
130
- dest_con <- con_from_src_or_con(dest )
131
-
132
- # in case `table_names` was chosen by the user, check if the input makes sense:
133
- # 1. is there one name per dm-table?
134
- # 2. are there any duplicated table names?
135
- # 3. is it a named character or ident_q vector with the correct names?
136
- if (is.null(table_names )) {
137
- table_names_out <- repair_table_names_for_db(src_names , temporary , dest_con , schema )
138
- # https://github.com/tidyverse/dbplyr/issues/487
139
- if (is_mssql(dest )) {
140
- temporary <- FALSE
141
- }
142
- } else {
143
- if (! is.null(schema )) abort_one_of_schema_table_names()
144
- if (is_function(table_names ) || is_bare_formula(table_names )) {
145
- table_name_fun <- as_function(table_names )
146
- table_names_out <- set_names(table_name_fun(src_names ), src_names )
147
- } else {
148
- table_names_out <- table_names
149
- }
150
- check_naming(names(table_names_out ), src_names )
151
-
152
- if (anyDuplicated(table_names_out )) {
153
- problem <- table_names_out [duplicated(table_names_out )][[1 ]]
154
- abort_copy_dm_to_table_names_duplicated(problem )
155
- }
94
+ if (! is_db(dest )) {
95
+ deprecate_stop(
96
+ " 0.1.6" , " dm::copy_dm_to(dest = 'must refer to a DBI connection')" ,
97
+ " dm::collect.dm()"
98
+ )
99
+ }
156
100
157
- names(table_names_out ) <- src_names
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
158
113
}
159
114
} else {
160
- # FIXME: Other data sources than local and database possible
161
- deprecate_warn(
162
- " 0.1.6" , " dm::copy_dm_to(dest = 'must refer to a remote data source')" ,
163
- " dm::collect.dm()"
164
- )
165
- table_names_out <- set_names(src_names )
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 )
123
+
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
+ }
128
+
129
+ names(table_names_out ) <- src_names
166
130
}
167
131
168
- # FIXME: if same_src(), can use compute() but need to set NOT NULL and other
169
- # constraints
132
+ table_names_out <- ddl_check_table_names(table_names_out , dm )
170
133
171
- # Shortcut necessary to avoid copying into .GlobalEnv
172
- if (! is_db(dest )) {
173
- return (dm )
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 )
174
142
}
175
143
176
- 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 )
145
+
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 )
177
152
178
- ticker_create <- new_ticker(
153
+ ticker_pre <- new_ticker(
179
154
" creating tables" ,
180
- n = length(queries $ sql_table ),
155
+ n = length(pre ),
181
156
progress = progress ,
182
157
top_level_fun = " copy_dm_to"
183
158
)
184
159
185
160
# create tables
186
- walk(queries $ sql_table , ticker_create (~ {
161
+ walk(pre , ticker_pre (~ {
187
162
DBI :: dbExecute(dest_con , .x , immediate = TRUE )
188
163
}))
189
164
190
- ticker_populate <- new_ticker(
165
+ ticker_load <- new_ticker(
191
166
" populating tables" ,
192
- n = length(queries $ name ),
167
+ n = length(load ),
193
168
progress = progress ,
194
169
top_level_fun = " copy_dm_to"
195
170
)
196
171
197
172
# populate tables
198
- pwalk(
199
- queries [c(" name" , " remote_name" )],
200
- ticker_populate(~ db_append_table(
201
- con = dest_con ,
202
- remote_table = .y ,
203
- table = dm [[.x ]],
204
- progress = progress ,
205
- autoinc = dm_get_all_pks(dm , table = !! .x )$ autoincrement
206
- ))
207
- )
173
+ walk(load , ticker_load(~ {
174
+ DBI :: dbExecute(dest_con , .x , immediate = TRUE )
175
+ }))
208
176
209
- ticker_index <- new_ticker(
177
+ ticker_post <- new_ticker(
210
178
" creating indexes" ,
211
- n = sum(lengths( queries $ sql_index ) ),
179
+ n = length( post ),
212
180
progress = progress ,
213
181
top_level_fun = " copy_dm_to"
214
182
)
215
183
216
184
# create indexes
217
- walk(unlist( queries $ sql_index ), ticker_index (~ {
185
+ walk(post , ticker_post (~ {
218
186
DBI :: dbExecute(dest_con , .x , immediate = TRUE )
219
187
}))
220
188
221
189
# remote dm is same as source dm with replaced data
190
+ # FIXME: Extract function
222
191
def <- dm_get_def(dm )
223
192
224
193
remote_tables <- map2(
225
194
table_names_out ,
226
195
map(def $ data , colnames ),
227
- ~ tbl(dest_con , ..1 , vars = ..2 )
196
+ ~ tbl(dest_con , .x , vars = .y )
228
197
)
229
198
230
- def $ data <- unname(remote_tables [names( dm )] )
199
+ def $ data <- unname(remote_tables )
231
200
remote_dm <- dm_from_def(def )
232
201
233
202
invisible (debug_dm_validate(remote_dm ))
0 commit comments