Appending to an Array

I am querying a database using DBI and ODBC. After I run the execute, I
want to grab each row as an array, and add it to another array, essentially
creating an Array of Arrays. I've tried this two ways with the same result:

sth = dbh.execute("SELECT * FROM SOMETABLE")
rows = sth.fetch_all

and

rows = sth.fetch do |row|
    rows << row
end

The result for both is that the last row is repeated in the array however
many times there are rows. Why isn't it appending correctly?

Thanks,

Anthony

Probably because the DB driver optimizes object allocation and reuses
the same instance. Then this is what happens:

irb(main):006:0> rows =
=>
irb(main):007:0> a = %w{a b c d}
=> ["a", "b", "c", "d"]
irb(main):008:0> rows << a
=> [["a", "b", "c", "d"]]
irb(main):009:0> a[2] = 99
=> 99
irb(main):010:0> rows << a
=> [["a", "b", 99, "d"], ["a", "b", 99, "d"]]

The phenomenon is called "aliasing".

You can solve it by copying row Arrays.

rows =

sth.fetch do |row|
  rows << row.to_a # if rows is not an Array
  rows << row.dup # if rows is an Array
end

Kind regards

robert

···

On Tue, Feb 7, 2012 at 10:27 PM, Anthony Simonelli <asimonelli01@gmail.com> wrote:

I am querying a database using DBI and ODBC. After I run the execute, I
want to grab each row as an array, and add it to another array, essentially
creating an Array of Arrays. I've tried this two ways with the same result:

sth = dbh.execute("SELECT * FROM SOMETABLE")
rows = sth.fetch_all

and

rows = sth.fetch do |row|
rows << row
end

The result for both is that the last row is repeated in the array however
many times there are rows. Why isn't it appending correctly?

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Would `Array(row)` not be a clean implementation of this ?

peterv@ASUS:~$ irb
001:0> row = "a string"
=> "a string"
002:0> Array(row)
=> ["a string"]
003:0> row = [:array_entry]
=> [:array_entry]
004:0> Array(row)
=> [:array_entry]

Peter

···

On Tue, Feb 7, 2012 at 11:04 PM, Robert Klemme <shortcutter@googlemail.com>wrote:

On Tue, Feb 7, 2012 at 10:27 PM, Anthony Simonelli > <asimonelli01@gmail.com> wrote:
> I am querying a database using DBI and ODBC. After I run the execute, I
> want to grab each row as an array, and add it to another array,
essentially
> creating an Array of Arrays. I've tried this two ways with the same
result:
>
> sth = dbh.execute("SELECT * FROM SOMETABLE")
> rows = sth.fetch_all
>
> and
>
> rows = sth.fetch do |row|
> rows << row
> end
>
> The result for both is that the last row is repeated in the array however
> many times there are rows. Why isn't it appending correctly?

Probably because the DB driver optimizes object allocation and reuses
the same instance. Then this is what happens:

irb(main):006:0> rows =
=>
irb(main):007:0> a = %w{a b c d}
=> ["a", "b", "c", "d"]
irb(main):008:0> rows << a
=> [["a", "b", "c", "d"]]
irb(main):009:0> a[2] = 99
=> 99
irb(main):010:0> rows << a
=> [["a", "b", 99, "d"], ["a", "b", 99, "d"]]

The phenomenon is called "aliasing".

You can solve it by copying row Arrays.

rows =

sth.fetch do |row|
  rows << row.to_a # if rows is not an Array
rows << row.dup # if rows is an Array
end

Judge for yourself:

irb(main):001:0> a = [:x]
=> [:x]
irb(main):002:0> b = Array(a)
=> [:x]
irb(main):003:0> b.equal? a
=> true
irb(main):004:0> a.object_id == b.object_id
=> true

Kind regards

robert

···

On Tue, Feb 7, 2012 at 11:22 PM, Peter Vandenabeele <peter@vandenabeele.com> wrote:

On Tue, Feb 7, 2012 at 11:04 PM, Robert Klemme > <shortcutter@googlemail.com>wrote:

On Tue, Feb 7, 2012 at 10:27 PM, Anthony Simonelli >> <asimonelli01@gmail.com> wrote:
> I am querying a database using DBI and ODBC. After I run the execute, I
> want to grab each row as an array, and add it to another array,
essentially
> creating an Array of Arrays. I've tried this two ways with the same
result:
>
> sth = dbh.execute("SELECT * FROM SOMETABLE")
> rows = sth.fetch_all
>
> and
>
> rows = sth.fetch do |row|
> rows << row
> end
>
> The result for both is that the last row is repeated in the array however
> many times there are rows. Why isn't it appending correctly?

Probably because the DB driver optimizes object allocation and reuses
the same instance. Then this is what happens:

irb(main):006:0> rows =
=>
irb(main):007:0> a = %w{a b c d}
=> ["a", "b", "c", "d"]
irb(main):008:0> rows << a
=> [["a", "b", "c", "d"]]
irb(main):009:0> a[2] = 99
=> 99
irb(main):010:0> rows << a
=> [["a", "b", 99, "d"], ["a", "b", 99, "d"]]

The phenomenon is called "aliasing".

You can solve it by copying row Arrays.

rows =

sth.fetch do |row|
rows << row.to_a # if rows is not an Array
rows << row.dup # if rows is an Array
end

Would `Array(row)` not be a clean implementation of this ?

peterv@ASUS:~$ irb
001:0> row = "a string"
=> "a string"
002:0> Array(row)
=> ["a string"]
003:0> row = [:array_entry]
=> [:array_entry]
004:0> Array(row)
=> [:array_entry]

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/