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


B

Brian Candler

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

Advertisements

B

Brian Candler

--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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 <[email protected]>
To: (e-mail address removed)
Subject: Problem with ruby-dbi-all-0.0.20 and/or ruby-1.8.0
Message-ID: <[email protected]>
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--
 
B

Brian Candler

B> def clone
B> clone_with(@arr.dup)
B> end

alias dup clone

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

ts

B> alias :dup :clone

Why ? alias is a keyword

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


Guy Decoux


-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
Ruby-dbi-devel mailing list
(e-mail address removed)
https://lists.sourceforge.net/lists/listinfo/ruby-dbi-devel
 
Ad

Advertisements

B

Brian Candler

B> alias :dup :clone

Why ? alias is a keyword

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.
 

Top