Двойной вызов следующей функции приведет к ошибке в Windows, но не в Ubuntu. Я пробовал на двух машинах каждую. Это связано с DBI::dbSendQuery() - если это закомментировано, функция может выполняться повторно без ошибок. На всех четырех машинах установлены uckdb v1.0.0 и DBI v1.2.3. Это происходит (с аналогичными сообщениями об ошибках), если аргументы находятся внутри или вне вызова uckdb::duckdb().
Единственное решение, которое я нашел, это сохранять соединение открытым на протяжении всего выполнения. Требуется перезапустить R (т. е. ctl+shift+F10 в RStudio), чтобы иметь возможность снова обратиться к тому же файлу DuckDB.
Что я могу сделать по-другому?
path_db <- "~/so-question.duckdb"
f <- function() {
sql_1 <-
"
DROP TABLE if exists t1;
CREATE TABLE t1 (
id int primary key,
s text not null,
);
"
sql_2 <- "SHOW ALL TABLES;"
cn <- DBI::dbConnect(duckdb::duckdb(), dbdir = path_db, bigint = "integer64")
# Alternative connection
# cn <- DBI::dbConnect(duckdb::duckdb(dbdir = path_db, bigint = "integer64"))
ds_1 <- DBI::dbSendQuery(cn, sql_1)
ds_2 <- DBI::dbGetQuery(cn, sql_2)
DBI::dbDisconnect(cn, shutdown = TRUE)
rm(cn)
ds_2
}
f()
# database schema name column_names column_types temporary
# 1 so-question main t1 id, s INTEGER, VARCHAR FALSE
f() # Throws an error in Windows, but not Ubutu.
выход:
Error: rapi_startup: Failed to open database: {"exception_type":"IO","exception_message":"File is already open in \nC:\\Program Files\\RStudio\\resources\\app\\bin\\rsession-utf8.exe (PID 14948)"}
выход из альтернативного соединения:
Error in h(simpleError(msg, call)) :
error in evaluating the argument 'drv' in selecting a method for function 'dbConnect': rapi_startup: Failed to open database: {"exception_type":"IO","exception_message":"File is already open in \nC:\\Program Files\\RStudio\\resources\\app\\bin\\rsession-utf8.exe (PID 12140)"}
@krlmlr, теперь это работает на всех четырех машинах. Если вы ответите, я буду рад принять это и добавить к вашим 25 тысячам.
@krlmlr, я надеялся поставить gc() внутри f(), чтобы вызывающий абонент не отвечал за вызовы более низкого уровня. Но он выдает ту же ошибку, если он внутри. Есть идеи, как избежать возложения этой ответственности на пользователя?
Может существовать указатель назад от ds_1, который удаляется только после выхода f(). Если это не удастся, это может быть новый вопрос с отдельным репрексом.
Это потрясающе. Да, замена ds_1 <- DBI::dbSendQuery(cn, sql_1) на просто DBI::dbSendQuery(cn, sql_1) работает.
Зачем вообще нужен dbSendQuery()? В данном случае это бесполезно, просто дорого.
Понял, создание таблицы. dbExecute() лучше, чем dbSendQuery() здесь.
Я вижу преимущества dbExecute() и предполагаю, что его вызов dbClearResult() поможет снять некоторую блокировку? В результате gc() больше не нужен, верно? По крайней мере, на моих машинах этого не происходит.
Да, dbSendQuery() возвращает объект результата, dbExecute() уже очищает его.





Последние версии пакета Duckdb R отключаются правильно, но необходимо вызвать сбор мусора.
path_db <- "~/so-question.duckdb"
f <- function() {
sql_1 <-
"
DROP TABLE if exists t1;
CREATE TABLE t1 (
id int primary key,
s text not null,
);
"
sql_2 <- "SHOW ALL TABLES;"
cn <- DBI::dbConnect(duckdb::duckdb(), dbdir = path_db, bigint = "integer64")
# Alternative connection
# cn <- DBI::dbConnect(duckdb::duckdb(dbdir = path_db, bigint = "integer64"))
# Use dbExecute() for side effects
DBI::dbExecute(cn, sql_1)
ds_2 <- DBI::dbGetQuery(cn, sql_2)
# No longer need shutdown = TRUE
DBI::dbDisconnect(cn)
rm(cn)
# This is needed
gc()
ds_2
}
Что произойдет, если вы
gc()между двумя вызовами?