如何防止在R中截断错误消息

lit*_*ngs 9 error-handling r rjdbc

我正在使用RJDBC查询R中的数据库.查询是根据从文件读入的数据构建的.这些查询可能会变得很长,并且可能包含不存在的列(导致错误).

下面是一个简化示例,它将文件作为输入,并从文件生成运行2查询.

table     column
drinks    cost
drinks    sugar
drinks    volume
food      cost
SELECT column, cost, sugar FROM drinks;
SELECT cost FROM food;
Run Code Online (Sandbox Code Playgroud)

由于这些查询可能会变得很长,因此数据库中的任何错误通常会在有用信息之前被截断.我目前的一个错误是:

错误[2018-05-16 16:53:07]错误处理表data_baseline_biosamples为DAR-2018-00008原始错误消息:.verify.JDBC.result中的错误(r,"无法检索JDBC结果集",::Unable检索SELECT ed.studyid的JDBC结果集,{非常长的列列表},ct.nmr_xl_vldl_pl,ct.nmr_xl_

由于数据库错误包括密钥信息之前的整个查询,因此截断会删除有用的信息以解决问题.

在这种情况下,错误消息可能以这样的结尾:

(第1行,'littlefeltfangs'拥有的表'data_biosamples'不包含列'sample_source'.)

如何记录数据库发送的完整错误消息或以其他方式提取该消息的最后部分?

我在tryCatch中捕获错误并使用futile.logger将错误传递到日志文件中.截断时的总错误长度为8219个字符,其中8190个出现在数据库中.

Mic*_*ico 9

这不是RJDBC切断错误信息.

?stop:

错误将被截断为getOption("warning.length")字符,默认为1000.

所以你可以设置选项:

stop(paste(rep(letters, 50L), collapse = ''))
options(warning.length = 2000L)
stop(paste(rep(letters, 50L), collapse = ''))
Run Code Online (Sandbox Code Playgroud)

您会注意到第一条消息中的截断,但没有第二条消息.

对于我自己的帮助函数捕获错误RDJBC,我使用类似的东西:

result = tryCatch(<some DB operation>, error = identity)
Run Code Online (Sandbox Code Playgroud)

然后执行正则表达式result$message以测试各种常见错误并生成更友好的错误消息.


未提及的?stop是,warning.length只能在相当窄的值范围内.为了探索这个,我运行了以下代码:

can = logical(16000L)
for (ii in seq_along(can)) {
  res = tryCatch(options(warning.length = ii),
                 error = identity)
  if (inherits(res, 'error')) {
    can[ii] = FALSE
  } else can[ii] = TRUE
}

png('~/Desktop/warning_valid.png')
plot(can, las = 1L, ylab = 'Valid option value?',
     main = 'Valid option values for `warning.length`',
     type = 's', lwd = 3L, log = 'x')
first = which.max(can)
switches = c(first, first + which.min(can[first:length(can)] - 1L))
abline(v = switches, lty = 2L, col = 'red', lwd = 2L)
axis(side = 1L, at = switches, las = 2L, cex = .5)
dev.off()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

打败我这些数字(100和8172)来自哪里,它们看起来相当随意(8196是2的最接近的幂).是R源中的地方,这些值是硬编码的.我已经问过这个问题r-devel ; 我会相应更新这篇文章.

FWIW,在我自己的错误解析帮助函数(为查询PrestoDB而构建)中,我有这一行:

core_msg = gsub('.*(Query failed.*)\\)\\s*$', '\\1', result$message)
Run Code Online (Sandbox Code Playgroud)

这是为了迎合PrestoDB出来的错误消息,所以你必须自己定制它,但想法是剪掉你的错误消息的一部分,这只是反驳查询本身.

或者,当然您可以分成result$message两个小于8172字符的位并分别打印出来.