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

时间:2018-05-17 09:14:36

标签: r error-handling rjdbc

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

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

table     column
drinks    cost
drinks    sugar
drinks    volume
food      cost
SELECT column, cost, sugar FROM drinks;
SELECT cost FROM food;

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

  

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

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

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

  

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

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

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

2 个答案:

答案 0 :(得分:7)

RJDBC没有切断错误消息。

请参阅?stop

  

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

所以你可以设置选项:

stop(paste(rep(letters, 50L), collapse = ''))
options(warning.length = 2000L)
stop(paste(rep(letters, 50L), collapse = ''))

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

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

result = tryCatch(<some DB operation>, error = identity)

然后在result$message上执行正则表达式以测试各种常见错误&amp;产生更友好的错误信息。

?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()

enter image description here

在这些数字(100&amp; 8172)来自的地方打败我,它们看起来相当随意(8196是最近的2的幂)。 Here是R源中的位置,其中这些值是硬编码的。我是asked about this on r-devel;我会相应地更新这篇文章。

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

core_msg = gsub('.*(Query failed.*)\\)\\s*$', '\\1', result$message)

这适用于PrestoDB发出的错误消息,因此您必须自己进行自定义,但我们的想法是剪掉您错误消息的那部分,这只会反驳查询本身。< / p>

或者,您当然可以将result$message分成两个小于8172个字符的位,然后单独打印出来。

答案 1 :(得分:0)

虽然不是一般情况的解决方案,但我的具体案例的解决方案是从使用RJDBC包转移到odbc包(而不是RODBC包)。两者都基于DBI,这意味着切换应该像安装ODBC驱动程序和替换dbConnect参数一样简单。 odbc包生成的错误消息不包含原始查询,因此不要遇到我正在努力解决的截断问题。

为了进行比较,这是我需要做出的一整套改变:

原件:

request_settings[['db_con']]<-dbConnect(global_settings$ingresJDBC,url="jdbc:ingres://localhost:IJ7/myvnode::mydatabase;")

新:

request_settings[['db_con']]<-dbConnect(odbc::odbc(),driver="Ingres",server="myvnode",database="mydatabase")

错误消息更加紧凑。如,

  

错误在new_result(连接@ PTR,语句):nanodbc / nanodbc.cpp:1344:42501:[Actian] [Ingres的ODBC驱动程序] [安格尔]线路1,表 'MYTABLE' 由 'littlefeltfangs' 拥有不包含列'mycolumn'。

可以找到odbc包的文档(它的内容)here