I know there's already a heluvalot of DBIx modules, but I just couldn't help myself. I do not want an ORM, but rather a simple way to call my stored procedures, including the ones with output parameters.

I started with DBIx::LazyMethod and extended it to infer the arguments and support the output parameters for MSSQL stored procedures, but I was unable to contact the author for quite some time (and succeeded only after halfway in the rewrite) to have the changes included and decided to rewrite the stuff to make it quicker. Instead of going through the AUTOLOAD in ever call, I generate the code you'd otherwise write yourself, with the prepare(), bind_param(), bind_param_inout() and execute() and based on the way you want the results even the fetchrow_xxx() and eval"" it so that it gets called directly next time.

use DBIx::Declare MyDB => { data_source => "dbi:ODBC:Driver=SQL Server;Server=Some;Database=M +yDB", type => 'MSSQL', user => '...', pass => '....', attr => { 'RaiseError' => 0, 'AutoCommit' => 1, LongReadLen => 655 +36 }, methods => { GetSiteName => { return => '$$', # assuming CREATE PROCEDURE GetSiteName(@Id in +t, @Name varchar(100) OUTPUT) ... }, FetchSiteDetails => { return => '_%', }, FetchSiteList => '@%', InsertSite => '@%', FetchFreeSiteList => { sql => 'SELECT Id, Name FROM Sites WHERE Cost = 0 and Name lik +e '%'+? ORDER BY Name', args => ['Name'], defaults => {Name => ''}, return => '@%', } } }; my $db = MyDB->new(); my $site_name = $db->GetSiteName( $id); my $details = $db-> FetchSiteDetails( -SiteId => $id); print "$details->{Name} costs $details->{Cost}\n"; my @free_sites = $db->FetchFreeSiteList(); my @free_sites_starting_a = $db->FetchFreeSiteList(-Name => 'a');

You may also use this as a way to keep all your queries on one place if you do not use stored procedures.

It's still beta, though there are test scripts for MSSQL, mysql and SQLite (stored procedures argument inference only works for MSSQL so far). If it looks like you might have a use for a beast like this please have a look at the docs and the module at my pages and let me know.

Update: I expect to add support for stored procedures in mysql as well, but would need help with their support in Oracle or PostgreSQL.

Update 2009-06-05: I just released version 0.01.006 with a lot of tests (and fixes) and the code caching implemented. You can find it on my pages.

Thanks, Jenda
Enoch was right!
Enjoy the last years of Rome.

  • Comment on RFC: DBIx::Declare - generate code to call stored procs/SQL statements
  • Download Code

Replies are listed 'Best First'.
Re: RFC: DBIx::Declare - generate code to call stored procs/SQL statements
by wazoox (Prior) on May 21, 2009 at 19:35 UTC
    That's very nice, it's exactly the way I usually do it, though I usually wrote an ad hoc module for every program... I'm happy to see your laziness and hubris have beaten me :)

      Thanks :-) Do you have any suggestions regarding what you'd like the module to support? As I wrote I plan to add support for stored procedures in mysql, but I have neither Oracle nor PostgreSQL and do not need to support them myself. Another thing I consider adding is the ability to write the generated methods to the disk (or maybe some other cache as well?) and load them from there by the next instance of the script, though I'm not sure how big improvement would that be. And possibly some way to have all the methods generated right away instead of on the first use and optionally written somewhere. That way you might be able to generate all the code and later use the generated code directly instead of this module.

      Even as it is you can use the module to generate the method and copy&paste it somewhere. If you set the environment variable DBIx_Declare_Debug (before the first use DBIx::Declare ... in your script) you get some debug info and the generated code or if you set the $db->{_show_generated_code} to a true value, you get just the generated code on STDOUT.

      Jenda
      Enoch was right!
      Enjoy the last years of Rome.

        Well, I don't actually care about Oracle, but postgres is a must-have for me :) I'll have a look at your code, but right now I'm upgrading my machine and still haven't reinstalled postgresql :)