Tim,

I spoke to you briefly at the OSCON last week during the Perl Lightning Talks (I gave one on SQL::Translator). Though I didn't raise my hand when you asked for people to contribute to a DBI module for Perl 6, I've had some ideas that I thought about sharing. Part of what I'm thinking is based on the "7 Principles of Better API Design" tutorial I heard Damian give earlier in the week. There he made a point that a great place to start designing a module is to first decide how you want to use/call it, and I definitely agree with that. So I thought I might send you some ideas about P6 DBI API.

1) I respectfully submit to use "new" instead of "connect" to instantiate a connection.

And since I always include "{ RaiseError => 1 }," I would request that this argument be the default and that someone would have to turn this off explicitly.

I would also like to see the DSN change since they all start with "dbi:" -- couldn't that be left off, then? I would also love to see some standardization on the driver names ("mysql" when it's normally written "MySQL," "Pg" when the db is called "PostgreSQL," etc.). Also, WRT there being "no standard for the text following the driver name," perhaps there should be?

use DBI;

my $dbh = DBI.new( driver => 'MySQL', dsn => 'host=cabot;database=markers30', user => 'web_ro' ... );

2) Damian harped on having to write things on every call, and I have definitely found the middle hashref arg to most DBI calls to be irksome as for me using MySQL/Pg/SQLite almost all my Perl career, I've only ever passed "{}" (except for "{ Columns => {} }" on "selectall_arrayref"). So I'd love to see that arg go away, and I'm assuming that with P6 sub prototypes that you won't have to worry so much about positional args and can get rid of that anyway. Perhaps all the args should be named, which is particularly easy with the new pair syntax:

my $data = $dbh.selectcol_arrayref( :$sql, :@args, :%option );

3) Another thing I'd like to suggest is a wholesale revamp of the method names with an eye towards throwing out most of them, or, if not that, then adding a new method that uses something like Contextual::Return's ability to figure out the right thing to return:

my @data = $dbh.get( :$sql ); # returns an array
my $iter = $dbh.get( :$sql ); # returns an iterator

Likewise, each member of the array or iterator could be polymorphic depending on how it's used.

for my $obj ( @data ) {
    print $obj.{'foo'};
    print $obj.[0];
}

4) In addition to getting rows back as array/hash refs, perhaps add an object interface either that uses (santized) column names as (read- only) accessors or has a general-purpose accessor. The idea here is to throw an exception when someone requests a non-existent column:

my $sql = 'select foo, bar from baz';
my $iter = $dbh.get( :$sql );

while ( my $rec = $iter.next ) {
    my $foo = $rec.foo;
    my $bar = $rec.value('bar');
    my $q1  = $rec.quux; # exception as there is no "quux" selected
    my $q2  = $rec.value('quux'); # another exception
}

I added something like this in my Text::RecordParser module:

        
http://search.cpan.org/dist/Text-RecordParser/lib/Text/RecordParser/Object.pm

That's all I can think of for now.

ky

Reply via email to