0

考虑这个程序

require 'dbi'

handle = DBI.connect('DBI:Mysql:tasks', 'root', 'stupid')

handle.select_all('select * from tasks') do |row|
  puts row.inspect
end

rows = handle.select_all('select * from tasks')
puts rows.inspect

第一次调用select_all被传递一个块,它使用它来遍历表行,就像它假设的那样。这是用于迭代的标准 Ruby 习惯用法,所以它当然可以工作。

第二次调用应返回相同的数据,但一次全部打包在一个数组中。数组实际上包含的是表格的最后一行!

这是一个错误,还是我做错了什么?

4

2 回答 2

1

我也偶然发现了这个。经过大量研究,我决定DBI::Row与特定语句相关的每个实例都引用相同的内存。更糟糕的是,复制或克隆它没有任何区别。获得正确副本的唯一方法是将其转换为数组,.to_a这意味着您将丢失方法:(

我不厌其烦地提交了一份关于 ruby​​forge 的错误报告——不是因为我认为它会得到修复,而是因为它可能会帮助其他一些正在拔头发的傻瓜。

于 2012-12-04T21:04:21.847 回答
0

I just stumbled across this too. After considerable research I have decided that every instance of DBI::Row associated with a particular statement hand reference the same memory. Worse still dup or cloning it makes no difference. The only way to get a proper copy is to convert it to an array with .to_a which means you loose the methods :(

I took the trouble to file a bug report on rubyforge -- not because I think it will get fixed but because it may help some other sucker who is pulling their hair out.

In fact I have just finished converting a couple of scripts over to Sequel from DBI. Sequel looks very nice as it allow both ORM type access as well as supporting raw sql like dbi.

Translation was straight forward.

于 2012-12-05T01:40:26.447 回答