Brian Candler wrote:
While we're talking about DBI NG, is there a overriding reason why DBI
returns a DBI::Row instead of just a plain array?
Yes. It's easier to access columns by name or by position.
You don't need to "fetch_hash" (by name) or "fetch_array" (by position).
Otherwise you can't use "each" and the like for both.
It could be possible to return a duplicated DBI::Row object, but the
decision was to do not. The only problem you get is when you use the
complete row.
sth.execute
rows = sth.collect do |row|
row # error
end
But why would you do that if there's sth.fetch_all which does the same,
but correct (okay, maybe in case of sth.select)
And if you access columns, then there's no need for dup-ing the row object.
rows = sth.collect do |row|
row['col']
end
I've not done any performance comparisons, using #dup by default or not.
I agree, that is's ugly to use #dup. If performance doesn't hurt, we can
use the dup-ing by default. Any comments?
But I don't like dbh['DupByDefault'] = true/false. The less
state-dependent, the better.
BTW, using enumerator, you could do:
sth.to_enum(:fetch_array).each do |row|
...
end
or:
sth.to_enum(:fetch_hash).each do |row|
...
end
DBI::Row objects do not consume too much memory by itself. They only
reference the row data and the column information, so duping is relative
"light".
The methods of DBI::Row are not documented at
http://ruby-dbi.rubyforge.org/DBI_SPEC.html
and I always just use the array accessors. And the fact that the DBI::Row
object itself is mutated for each row is a pain. Usually the strings it
contains are new objects, so as long as you remember r.dup then you're OK;
but I've certainly had programming errors in the past because of this, and
it's something which is confusing when you read the documentation.
I'd be much happier if:
- DBI methods returned a vanilla array rather than a DBI::Row
Hm, you don't use column names very often? Any row['col'] would no more
work!
- there were a separate object which contained the column number<->name
mapping, available if requested (I've never needed it)
I suppose the only benefit of DBI::Row at the moment is that you can do
r.to_h
to get a hash of 'colname'=>value. This could become
DBI::makehash(r, colnames)
Or if colnames were stored in an object of their own,
colnames.makehash(r)
Aside: I am perplexed by this bit of code in DBI::Row#conv_param
if p.exclude_end?
(first..last)
else
(first..last)
end
I think there must be a dot missing. I presume there's no unit-test for this
method :-)
right.
well, DBI::Row is too complex, it allows you to do things like:
row[/col/i] # returns all values which column name matches /col/i
row[1..10] # columns 1 to 10
row[0, 2..4] # columns 0 and 2 to 4
row['col1' .. 'col5']
and so on....
In DBI NG the functionality will probably reduced.
Regards,
Michael
|