digitalmars.D.learn - Storing classes in an array.
- Jeremy Cowgar (24/24) Apr 14 2005 I am having a bit of a problem. I have a function called fetchRow that
- Kris (21/45) Apr 14 2005 The problem probably lies in how r.setValues() operates ~ apparently, th...
- Jeremy Cowgar (7/31) Apr 15 2005 Kris,
- Kris (12/43) Apr 15 2005 Cool :-)
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
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
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
Cool :-) "Jeremy Cowgar" <jeremy __no_spam__.cowgar.cooooom> wrote in message news:d3oe7u$chr$1 digitaldaemon.com...Kris wrote:thatThe problem probably lies in how r.setValues() operates ~ apparently,themethod 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 fromtheDB, you'll end up with all Row instances pointing into (or slicing into)thiscontent of the last row read. To fix this, you must copy the row-content from the DB. Two way to doit toare 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) fromtheeach field. You might consider referencing the entire row content fromusingRow object, but it's not necessary if you're using slicing. If you'rerowpointers instead, then you may need to explicitly hang onto the dup'dsourcecontent (depends upon the way you're doing things). Either way, you'll be copying the content provided by the external(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