Bugs: Browse | Submit New | Admin
When fetching the results of an SELECT Statement with fetch_all , a array is returned, which has (correctly) as many elements aus the query returns. But the Elements are all the same row (the last row). When i loop over the cursor with fetch, all rows are returned correctly. This did work with ruby_1.8.6 and ruby_1.8.7. Installed packages: - ruby-oci8 (2.0.4 x86-mingw32) - dbi (0.4.5) Testcase: -------------------------------------- require 'dbi' connect="DBI:OCI8:myoradb" user="uuuu" pwd="pppp" dbh = DBI.connect(connect, user, pwd) stmt=" select 'A' as Name from dual union select 'B' as Name from dual union select 'C' as Name from dual union select 'D' as Name from dual " sth = dbh.execute(stmt) rows = sth.fetch_all sth.finish p rows puts "-- rows read: #{rows.size}" sth = dbh.execute(stmt) while row = sth.fetch do printf "%s\n", row[0] end sth.finish -------------------------------------------------------------- this Example returns: [["D"], ["D"], ["D"], ["D"]] -- rows read: 4 A B C D
Add A Comment:
Date: 2011-12-12 19:54 Sender: Patrick Bennett I have the same problem with 1.9.2 and 1.9.3. rdbi isn't an option either - it's got a couple showstopper issues with mysql. dbi at least has always worked and it's api is much simpler than rdbi's (being forced to add fetch(:all), etc. calls to every select. Of course, that this has been open for a year makes me concerned. Although if the same people are working on rdbi that explains it's being flaky as well. :( ActiveRecord here I come? *gulp*
Date: 2011-11-02 16:18 Sender: Valerio Schiavoni Seen with ruby 1.9.2p312 (2011-08-11 revision 32926) A patch for this would be greatly appreciated.
Date: 2011-07-13 19:35 Sender: Eustáquio Rangel Guys, Is there any plan to release a patch to fix this behaviour, as Justin showed us? The code works perfectly. Thanks!
Date: 2011-02-14 12:36 Sender: Justin Ossevoort Okay, the problem is that DBI::Row doesn't supply it's own 'dup' method anymore (since Ruby 1.9.x) and falls back to the versions supplied in Object. The problem with these methods in Object is that they are (according to the documentation) meant to produce shallow copies of objects. The reason that this is not sufficient in this case is due to the use of 'DelegateClass(Array)', which makes that our Row object is actually comprised of 2 objects which both have to be duplicated. So to fix this problem one has only to use the old pre-Ruby-1.9 version of 'dup' or the possibly more correct: module DBI class Row if RUBY_VERSION =~ /^1\.9/ def dup row = super row.instance_variable_set :@arr, @arr.dup row end end end end I neglected to set the ':@_dc_obj' since that logic seems broken at the moment (it is used only once in the old 'dup' method and a similar use is done in the '__setobj__' delegate helper method but here the instance variable is called '@delegate_dc_obj', either way it doesn't seem to have any added value and it's probably best if they are removed IMHO).
Date: 2011-02-14 10:52 Sender: Justin Ossevoort I'm seeing this very problem on the 1.9.1 ruby bundled with debian squeeze. Here is a little program that I wrote to try and shed some light on the issue. It seems as if the DBI::Row#dup's @arr.dup fails for some reason. Testscript ---------- #!/usr/bin/env ruby1.9.1 require 'dbi' def query(c) c.execute(%q{ SELECT 'a' UNION SELECT 'b' UNION SELECT 'c' }) end def t1(c) p query(c).fetch_all # result: [["c"], ["c"], ["c"]] ; expected: [["a"], ["b"], ["c"]] end def t2(c) set = query(c).fetch_all puts "Set: #{set.object_id}" set.each do |row| puts "\tRow: #{row.object_id} (@arr=#{row.__getobj__.object_id})" row.each do |cell| puts "\t\tCell: #{cell.object_id}" end end end def t3(c) query(c).fetch do |row| puts "\tRow: #{row.object_id} (@arr=#{row.__getobj__.object_id})" row.each do |cell| puts "\t\tCell: #{cell.object_id}" end end end c = DBI.connect('dbi:Pg:testdb', 'user', 'pass') t1(c) puts "================================" t2(c) puts "================================" t3(c) Output ------ # ./t2.rb [["c"], ["c"], ["c"]] ================================ Set: 75162030 Row: 75161940 (@arr=75162120) Cell: 75161670 Row: 75161750 (@arr=75162120) Cell: 75161670 Row: 75161650 (@arr=75162120) Cell: 75161670 ================================ Row: 75157100 (@arr=75157530) Cell: 75157160 Row: 75155970 (@arr=75157530) Cell: 75156010 Row: 75160580 (@arr=75157530) Cell: 75156340
Date: 2011-01-08 05:30 Sender: Sam Baskinger I saw this behavior today with the Pg and Mysql drivers. The problem appears to be the different handling of row duplication in 1.9.x vs 1.8. If I copy the "dup" definition near line 270 of dbi/row.rb everything seems to work. In the mean time, I'm only using the sth.fetch {|row| ...} convention.
Date: 2010-12-16 16:15 Sender: Shane Emmons I just submitted a patch to the DBI guys to fix this in Ruby 1.9.2, hopefully everything works. You might also want to check out the work they're doing on the new RDBI library.
Date: 2010-11-14 17:21 Sender: Fawad Shaikh I did some further research. There seems to have been a change in the array push functionality in ruby 1.9.2 when it comes to pushing arrays and strings. It no longer seems to take the dup of an array, but instead the object itself (same __id). so as the DBI::Row objects are pushed into an array, it continues to only reference the same row as the same row (__id) is being "pushed" in the .each loop. If that makes sense...
Date: 2010-10-27 03:20 Sender: Fawad Shaikh I should add more details: ruby-oci8 (2.0.4) dbi (0.4.5)
Date: 2010-10-27 03:16 Sender: Fawad Shaikh It is working for me in ruby ruby 1.9.1p430, but this same thing happened to me in ruby 1.9.2
Date: 2010-10-25 19:23 Sender: oliver peng I did see it with the latest Ruby 1.9.2.