Dbi peculiar behavior

Hi all,

Ruby 1.6.7, dbi .16, oracle .2.11

I’m getting some odd behavior returning DBI::Row objects in iterative context. I think this is
because of the way dbi is designed (to re-use the same reference), but I still think the behavior
is wrong:

require “dbi”

class Test
def initialize
@dbh = DBI.connect(dsn,user,password)
@sth = @dbh.prepare(“select field1, field2 from some_table”)
@sth.execute
end

def myiter
while r = @sth.fetch
if block_given?
yield r.dup
else
return r
end
end
end
end

t = Test.new

t.myiter{|row|
row.push(“X”)
puts row.join(’, ')
}

if we assume our query returns 4 rows we get this:

data, data, X
data, data, X, X
data, data, X, X, X
data, data, X, X, X, X

Is this expected behavior or a bug? I realize one solution is to just dup the row in “myiter”,
but I wanted to check.

Regards,

Dan

You always want to #dup a row returned from a DBI fetch. The underlying
implementation re-uses the pointer, so from one fetch to the next,
the data the row references will change.

To prevent that from changing references to previously fetched rows,
those need to be #dup’s of the original fetched row.

– Dossy

···

On 2002.08.31, Daniel Berger djberge@v55host11.interprise.com wrote:

I realize one solution is to just dup the row in “myiter”,
but I wanted to check.


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)

Hi all,

Ruby 1.6.7, dbi .16, oracle .2.11

I’m getting some odd behavior returning DBI::Row objects in iterative context. I think this is
because of the way dbi is designed (to re-use the same reference), but I still think the behavior
is wrong:

require “dbi”

class Test
def initialize
@dbh = DBI.connect(dsn,user,password)
@sth = @dbh.prepare(“select field1, field2 from some_table”)
@sth.execute
end

def myiter
while r = @sth.fetch
if block_given?
yield r.dup
else
return r
end
end
end
end

t = Test.new

t.myiter{|row|
row.push(“X”)
puts row.join(’, ')
}

if we assume our query returns 4 rows we get this:

data, data, X
data, data, X, X
data, data, X, X, X
data, data, X, X, X, X

I get the correct output (with DBD::Pg):

data, data, X
data, data, X
data, data, X
data, data, X

Are you sure, you yield “r.dup” in myiter?

Could you print out “r.id” in myiter, before yielding “r.dup”.
The same in the application of myiter (print row.id)!

What’s the output?

Is this expected behavior or a bug? I realize one solution is to just dup the row in “myiter”,
but I wanted to check.

No, it’s a bug if you have to dup the row twice. One dup should suffice.

Regards,

Michael

···

On Sat, Aug 31, 2002 at 12:36:10AM +0900, Daniel Berger wrote: