Bugs: Browse | Submit New | Admin

[#28624] fetch_all returns array with all the same rows with ruby_1.9.1

Date:
2010-10-06 12:09
Priority:
3
Submitted By:
Michael M. (mat_pascal)
Assigned To:
Nobody (None)
Category:
None
State:
Open
Summary:
fetch_all returns array with all the same rows with ruby_1.9.1

Detailed description
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: Notepad

Please login


Followup

Message
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.

Attached Files:

Name Description Download
No Files Currently Attached

Changes:

No Changes Have Been Made to This Item