From: Brian Candler Date: 2003-08-05T23:11:51+09:00 Subject: Re: Problem with ruby-dbi-all-0.0.20 and/or ruby-1.8.0 --zYM0uCDKw75PZbzx Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Tue, Aug 05, 2003 at 10:40:06PM +0900, Brian Candler wrote: > The following test program works correctly with ruby-dbi-all-0.0.18 under > ruby-1.6.8, but not ruby-dbi-all-0.0.20 under ruby-1.8.0: OK, rolling back to dbi-0.0.18 didn't fix this, so I've dug around some more. The following program demonstrates the problem without any database access: ---- 8< ------------------------------------------------------------------ #!/usr/local/bin/ruby require 'dbi/row' res = [] r = DBI::Row.new(["col1","col2"],[nil,nil]) [["one",1],["two",2],["three",3]].each do |x,y| r["col1"] = x r["col2"] = y p r res << r.dup end p res # [["three", 3], ["three", 3], ["three", 3]] under ruby-1.8.0 ---- 8< ------------------------------------------------------------------ Now, looking at the definition of DBI::Row, it is based on delegation to Array. So I can boil it down to the following: ---- 8< ------------------------------------------------------------------ #!/usr/local/bin/ruby -w require 'delegate' class Foo < DelegateClass(Array) # distilled from DBI::Row def initialize(arr) @arr = arr super(@arr) end def clone_with(new_values) Foo.new(new_values) end def clone clone_with(@arr.dup) end end r = Foo.new([nil,nil]) res = [] [["one",1],["two",2],["three",3]].each do |x,y| r[0] = x r[1] = y p r res << r.dup end p res ---- 8< ------------------------------------------------------------------ $ ruby16 -v bug2.rb ruby 1.6.8 (2002-12-24) [i386-freebsd4.7] ["one", 1] ["two", 2] ["three", 3] [["one", 1], ["two", 2], ["three", 3]] <<< expected $ ruby18 -v bug2.rb ruby 1.8.0 (2003-08-04) [i386-freebsd4.7] ["one", 1] ["two", 2] ["three", 3] [["three", 3], ["three", 3], ["three", 3]] <<< actual under 1.8.0 So, it looks like DBI is depending on some behaviour of delegate, and/or 'dup' making use of 'clone', which is no longer true in 1.8.0 But I don't know how to fix this; adding my own 'dup' method to class Foo doesn't seem to help. Anybody got any ideas? Thanks, Brian. --zYM0uCDKw75PZbzx Content-Type: message/rfc822 Content-Disposition: inline Date: Tue, 5 Aug 2003 14:39:54 +0100 From: Brian Candler To: ruby-talk@ruby-lang.org Subject: Problem with ruby-dbi-all-0.0.20 and/or ruby-1.8.0 Message-ID: <20030805143954.A32611@linnet.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i The following test program works correctly with ruby-dbi-all-0.0.18 under ruby-1.6.8, but not ruby-dbi-all-0.0.20 under ruby-1.8.0: ------------------------------------------------------------------ #!/usr/local/bin/ruby -w require 'dbi' LIMIT = 100 d = DBI.connect('dbi:Mysql:somedatabase','root','') sql = "select col1,col2 from anytable" rows = [] d.execute(sql) do |sth| loop do row = sth.fetch p row # prints the right answer break if row.nil? rows << row.dup break if rows.size >= LIMIT end end p rows # prints the wrong answer ------------------------------------------------------------------ The problem is that the array 'rows' contains the last row repeated N times, instead of N different rows. This is despite the use of 'row.dup'. The object_id's of the elements of row are all different, but the contents are the same. I used mysql-ruby-2.4.4 in both cases. Regards, Brian. --zYM0uCDKw75PZbzx--