What's That Noise?! [Ian Kallen's Weblog]

Main | Next day (May 26, 2004) »

20040525 Tuesday May 25, 2004

Class::DBI riddles Sometimes Perl is wonderfully expressive and an extreme productivity tool; sublime, even. Other times, it is an enigma and a riddle rolled into one.

I recently grabbed Class::DBI (v0.96) off of CPAN to help me wire up some simple objects with lots of database attributes. Now, when roughing out objects in Perl, I typically find it quickest to declare a package in the file scope of my working code -- it's like having a runnable test for the package's code write there in fornt of you. Most of the time, that's just fine and dandy -- as the code matures or gets unwieldy, migrating it out into its own .pm module files is fine. But I noticed that with Class::DBI, all kinds of weirdness can ensue if you declare your packages outside of the .pm module file world. I'd seen goofiness with older version complaining about not finding 'db_Main' in the package and yaddada yada. This time around, I tried putting everything in the file scope i.e. so it looks like this:

#!/usr/bin/perl

use Class::DBI;

my @britons = Criminy->retrieve_all;
map { print $_,$/ } @britons;

package Criminy;
use base 'CriminyDBI';

Criminy->table('criminy');
Criminy->columns(All => qw(id foo bar));

package CriminyDBI;
use Class::DBI;
use base 'Class::DBI';
# someday, I'll have a dog and name him Django Hendrix
CriminyDBI->connection('dbi:mysql:test','django','hendrix'); 

But this totally fails...

Criminy can't SELECT 
FROM   criminy
: DBD::mysql::st execute failed: You have an error in your SQL syntax near 
'FROM   criminy
' at line 2 [for Statement "SELECT 
FROM   criminy
"] at /usr/lib/perl5/site_perl/5.8.0/DBIx/ContextualFetch.pm line 51.
 at ./criminy.pl line 5
However if I put each of those packages in their own .pm module file, it's totally happy. I can't explain it (and I really don't want to, it just sucks). Try it out, here's the mysql schema:
CREATE TABLE criminy (
  id int(11) NOT NULL auto_increment,
  foo varchar(32) default NULL,
  bar varchar(32) default NULL,
  PRIMARY KEY  (id)
) TYPE=MyISAM;
INSERT INTO criminy VALUES (1,'Led','Zeppelin');
INSERT INTO criminy VALUES (2,'Black','Sabbath');
INSERT INTO criminy VALUES (3,'Deep','Purple');
Anyway, the short answer: don't take any shortcuts. Declare your packages in their own file and Class::DBI will glide along swimmingly. ( May 25 2004, 11:52:22 PM PDT ) Permalink