Problem with ruby-dbi-all-0.0.20 and/or ruby-1.8.0

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.

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.

···

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:

  def clone
    clone_with(@arr.dup)
  end

     alias dup clone

end

Guy Decoux

alias :dup :clone

OK that works… thank you.

I assume that for ‘dup’ and ‘clone’, one used to be implemented in terms of
the other. Is there a comparison of these two methods anywhere? In the
Pickaxe it says:

“dup typically uses the class of the descendent object to create
the new instance”

But I’m not quite sure what that means. Is it saying that typically Foo#dup
is implemented by calling Foo.new (or self.class.new) ?

Cheers,

Brian.

···

On Tue, Aug 05, 2003 at 11:35:19PM +0900, ts wrote:

def clone
clone_with(@arr.dup)
end

 alias dup clone

alias dup clone

       alias :dup :clone

Why ? alias is a keyword

svg% ruby -e 'alias aa puts; aa "aa"'
aa
svg%

Guy Decoux

OK, that’s new to me. I got most of my syntax from the Pickaxe book, and
most of its examples use alias :foo :bar. ref_c_class.html is an exception.

Cheers,

Brian.

···

On Tue, Aug 05, 2003 at 11:46:21PM +0900, ts wrote:

alias dup clone

   alias :dup :clone

Why ? alias is a keyword