Thread overview
Storing classes in an array.
Apr 15, 2005
Jeremy Cowgar
Apr 15, 2005
Kris
Apr 15, 2005
Jeremy Cowgar
Apr 15, 2005
Kris
April 15, 2005
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
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
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
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