这是我的问题。我想知道我在R会话中有多少个开放的RODBC连接。也许这个问题与Show all open RODBC connections有关。
问题是,如果我没有将连接分配给变量,我将无法使用此功能,即我执行odbcConnect()
而不是channel<-odbcConnect()
,因为不会创建环境变量。
我查看了RODBC包的C代码,似乎有一个变量nChannels
,其中包含int
个打开的连接数。我可以从R调用此变量,甚至使用C函数吗?
R环境如何在这里发挥作用?还是完全无关?任何解释都将受到赞赏,因为我在这个领域非常新。如果我接近这一点的逻辑也是错误的,请提供建议。
答案 0 :(得分:1)
如果用户提交自己的代码,解决方案很简单:提供自己的函数odbcConnect
,该函数在内部记录调用,然后发送到{RODBC}包。也就是说,不要让用户直接访问RODBC包。
只要您为用户提供设置(即用户永远不会呼叫library(RODBC)
,也不会RODBC::odbcConnect
),此功能就可以使用。
但如果不是这样,即如果用户直接与RODBC包进行交互,则需要更进一步:您需要自己修改RODBC包。您可以通过在运行时修补函数来完成此操作,但这是相当高级的(并且很脆弱;如果RODBC升级并更改其实现,它会中断)。这是一个最小的例子:
log_connect_expr = quote(assign('.odbc_connections', .GlobalEnv$.odbc_connections + 1, .GlobalEnv))
log_close_expr = quote(assign('.odbc_connections', .GlobalEnv$.odbc_connections - 1, .GlobalEnv))
# Inject expression into a function body at a given position, counting either
# from the beginning or from the end (if `pos` < 0).
insert_in_body = function (body, expr, pos) {
body = as.list(body)
if (pos < 0) pos = length(body) + pos + 1
all_indices = seq_along(body)
before_indices = all_indices < pos
after_indices = all_indices >= pos
as.call(c(body[before_indices], expr, body[after_indices]))
}
# Insert log calls into function bodies, after any error checking.
local({
odbcDriverConnect = RODBC::odbcDriverConnect
body(odbcDriverConnect) = insert_in_body(body(odbcDriverConnect), log_connect_expr, -1)
odbcClose = RODBC::odbcClose
body(odbcClose) = insert_in_body(body(odbcClose), log_close_expr, 4)
assignInNamespace('odbcDriverConnect', odbcDriverConnect, getNamespace('RODBC'))
assignInNamespace('odbcClose', odbcClose, getNamespace('RODBC'))
})
# Initialize counter
.GlobalEnv$.odbc_connections = 0
替代方案,只需下载RODBC源代码,修改它,构建软件包并在本地安装。所有这些解决方案都是hacky,但比在RODBC的C内部搜索更好。
读取内部RODBC连接状态不切实际。首先,变量nChannels
似乎不是打开连接数的准确计数;它更像是一个上限,关闭连接不会减少计数器。
但即使它是准确的,你无论如何都无法阅读,因为变量被声明为static
,因此不会被导出。