View mode: basic / threaded / horizontal-split · Log in · Help
April 15, 2005
Storing classes in an array.
I am having a bit of a problem. I have a function called fetchRow that 
looks something like this:

Row fetchRow() {
  Row r = new Row();
  r.setValues(...);
  return r;
}

Thenk I have a function that loops through each row in a result set and 
collects the output of the above function appending it onto an array:

  Row[] fetchAll() {
    Row[] rows;
    Row row;

    while ((row = fetchRow()) !== null) {
      rows ~= row;
    }

    finish();

    return rows;
  }

My problem  is when I then loop through the array returned by fetchAll() 
I get the correct number of rows, but they are all equal to the value of 
the last fetchRow() result.

What am I doing wrong?

Jeremy
http://jeremy.cowgar.com
April 15, 2005
Re: Storing classes in an array.
The problem probably lies in how r.setValues() operates ~ apparently, that
method is setting the row fields to a pointer into the row content? Or a
slice of the row content?

Since the row-content is being overwritten each time you read one from the
DB, you'll end up with all Row instances pointing into (or slicing into) the
content of the last row read.

To fix this, you must copy the row-content from the DB. Two way to do this
are as follows:

- .dup the content when you assign it to each field. You can do this for
slices too. For example: field.content = row.content[mark..pos].dup;

- .dup the entire DB row-content, and assign slices (or pointers) from it to
each field. You might consider referencing the entire row content from the
Row object, but it's not necessary if you're using slicing. If you're using
pointers instead, then you may need to explicitly hang onto the dup'd row
content (depends upon the way you're doing things).

Either way, you'll be copying the content provided by the external source
(DB), which will ensure each row ratains the correct data.

Good luck.

- Kris


"Jeremy Cowgar" <jeremy@__no_spam__.cowgar.cooooom> wrote in message
news:d3ncaf$2bvj$1@digitaldaemon.com...
> I am having a bit of a problem. I have a function called fetchRow that
> looks something like this:
>
> Row fetchRow() {
>    Row r = new Row();
>    r.setValues(...);
>    return r;
> }
>
> Thenk I have a function that loops through each row in a result set and
> collects the output of the above function appending it onto an array:
>
>    Row[] fetchAll() {
>      Row[] rows;
>      Row row;
>
>      while ((row = fetchRow()) !== null) {
>        rows ~= row;
>      }
>
>      finish();
>
>      return rows;
>    }
>
> My problem  is when I then loop through the array returned by fetchAll()
> I get the correct number of rows, but they are all equal to the value of
> the last fetchRow() result.
>
> What am I doing wrong?
>
> Jeremy
> http://jeremy.cowgar.com
April 15, 2005
Re: Storing classes in an array.
Kris wrote:
> The problem probably lies in how r.setValues() operates ~ apparently, that
> method is setting the row fields to a pointer into the row content? Or a
> slice of the row content?
> 
> Since the row-content is being overwritten each time you read one from the
> DB, you'll end up with all Row instances pointing into (or slicing into) the
> content of the last row read.
> 
> To fix this, you must copy the row-content from the DB. Two way to do this
> are as follows:
> 
> - .dup the content when you assign it to each field. You can do this for
> slices too. For example: field.content = row.content[mark..pos].dup;
> 
> - .dup the entire DB row-content, and assign slices (or pointers) from it to
> each field. You might consider referencing the entire row content from the
> Row object, but it's not necessary if you're using slicing. If you're using
> pointers instead, then you may need to explicitly hang onto the dup'd row
> content (depends upon the way you're doing things).
> 
> Either way, you'll be copying the content provided by the external source
> (DB), which will ensure each row ratains the correct data.
> 
> Good luck.

Kris,

Thanks! Got it all sorted out, indeed you were right. The .dup did what 
I needed and now I understand why and how.

This is part of the D DBI I am writing. You can see the correct code now 
in Row.d . http://jeremy.cowgar.com/ddbi/ v0.1.2

Jeremy
April 15, 2005
Re: Storing classes in an array.
Cool :-)

"Jeremy Cowgar" <jeremy@__no_spam__.cowgar.cooooom> wrote in message
news:d3oe7u$chr$1@digitaldaemon.com...
> Kris wrote:
> > The problem probably lies in how r.setValues() operates ~ apparently,
that
> > method is setting the row fields to a pointer into the row content? Or a
> > slice of the row content?
> >
> > Since the row-content is being overwritten each time you read one from
the
> > DB, you'll end up with all Row instances pointing into (or slicing into)
the
> > content of the last row read.
> >
> > To fix this, you must copy the row-content from the DB. Two way to do
this
> > are as follows:
> >
> > - .dup the content when you assign it to each field. You can do this for
> > slices too. For example: field.content = row.content[mark..pos].dup;
> >
> > - .dup the entire DB row-content, and assign slices (or pointers) from
it to
> > each field. You might consider referencing the entire row content from
the
> > Row object, but it's not necessary if you're using slicing. If you're
using
> > pointers instead, then you may need to explicitly hang onto the dup'd
row
> > content (depends upon the way you're doing things).
> >
> > Either way, you'll be copying the content provided by the external
source
> > (DB), which will ensure each row ratains the correct data.
> >
> > Good luck.
>
> Kris,
>
> Thanks! Got it all sorted out, indeed you were right. The .dup did what
> I needed and now I understand why and how.
>
> This is part of the D DBI I am writing. You can see the correct code now
> in Row.d . http://jeremy.cowgar.com/ddbi/ v0.1.2
>
> Jeremy
Top | Discussion index | About this forum | D home