www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Storing classes in an array.

reply Jeremy Cowgar <jeremy __no_spam__.cowgar.cooooom> writes:
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
Apr 14 2005
parent reply "Kris" <fu bar.com> writes:
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
Apr 14 2005
parent reply Jeremy Cowgar <jeremy __no_spam__.cowgar.cooooom> writes:
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
Apr 15 2005
parent "Kris" <fu bar.com> writes:
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
Apr 15 2005