blue_cowdawg has asked for the wisdom of the Perl Monks concerning the following question:

I've run into this issue once before and thought I'd seen the last of it and it has resurfaced.

The solution last time was to get the latest and greatest DBD drivers loaded on the machine where the bad behavior was observed. This time I'm seeing the behavior for no apparent reason. All of the modules that I know about that are in play here are at their latest and greatest versions.

Here is the program in it's entirety:

#!/usr/bin/perl -w use Class::DBI::Loader; my $loader = Class::DBI::Loader -> new( dsn => "dbi:Pg:dbname=peter_bcdc", user => "pberghol", password => '$3cr3t$9u!rr31', # not real! options => { RaiseError => 1, AutoCommit => 1 }, namespace => 'Db', relationships => 1 ); while ( my $line=<DATA> ){ chomp $line; my ($given_name,$surname,$email) = split(",",$line); my $person = Db::Person -> find_or_create( {given_name => $given_name +, surname => $surname, email_addr=> $email } ); } exit(0); __END__ <data follows here, but is besides the point...>
When this is run I get the enigmatic error:
Use of uninitialized value in split at /usr/lib/perl5/site_perl/5.8.5/ +Class/DBI/Pg.pm line 26. "location" has no primary key at /usr/lib/perl5/site_perl/5.8.5/Class/ +DBI/Loader/Generic.pm line 164

Liar! It does too have a primary key!

create table location ( location_id serial not null primary key, location_name text not null );

So... any thoughts on how to either fix this or work around it? I'd hate to think I have to go back to my old ways of writing my own objects to handle tables...


Some investigating

Being the perpetually curious sort I decided to look at the module Class::DBI::Pg where the complaint is coming from and noticed the following query being executed:
SELECT indkey FROM ${catalog}pg_index WHERE indisprimary=true AND indrelid=( SELECT oid FROM ${catalog}pg_class WHERE relname = ?)
Manually executing the SQL and taking some scientific wild assed guesses (SWAG) as to what should be put in place of the placeholder I got the following result.
peter_bcdc=# SELECT indkey FROM pg_catalog.pg_index WHERE indisprimary=true AND indrelid=( SELECT oid FROM pg_catalog.pg_class WHERE relname = 'location'); indkey -------- 1 (1 row)
Not sure that was the result the module was expecting and yet that doesn't in my mind explain the error code. Still curious... still don't have an answer...

(Update) more investigation

Hacking away at the module Class::DBI::Pg and adding more and more diagnostic print statements in I made an interesting discovery. The last (so far) debugging statement I added prints out one of the parameters being passed to the module, which is the name of the table. Obverve this sniglet:

event_class event_date event_type instructor instructor_type_map "location"

Notice that the tables prior to "location" are not quoted but location is. Something tells me this is significant... further checking is in order here...

(LAST UPDATE) OK... found it

Once I renamed this table from "location" to "place" everything was hunky dory. That still leaves open the issue that in the future where anymonk might not have control over table names in a database schema this might raise its ugly head again. Things I am planning on following up on:

  1. Making sure "location" is not in some way a reserved word in either the SQL99 standard or in PostgreSQL
  2. Email to the module's author to figure this out further.
All in all, this has been fun to work through...

Prior to this I found out that Class::DBI::Loader and friends get upset when you have a table named "class" as does the Hibernate Java POJO persistance layer. Seems you can't have a Java POJO named "Class"... gee... I wonder why? :=)


Peter L. Berghold -- Unix Professional
Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

Replies are listed 'Best First'.
Re: Class::DBI::Loader misbehaves (can't find a primary key)
by Melly (Chaplain) on Oct 16, 2006 at 19:35 UTC

    It sounds like a bug - have you tested against other db engines?

    Can you post minimal code that reproduces the problem? - I'm happy to test against mysql.

    I note that "location" is specified as a non-reserved keyword (iirc) in the postgresql docs.

    My guess would be that it's being correctly quoted (as a keyword), but then failing a match later on due to the quotes - perhaps the bug has slipped by because it's only a problem if "location" is the primary key field? Have you tested when "location" is not the primary key?

    Tom Melly, tom@tomandlu.co.uk
          It sounds like a bug - have you tested against other db engines?

      No, I hadn't. I'd actually have to set up MySQL on my development machine and get it running! Also, the schema would have to be modified to use auto_increment instead of the SERIAL types I use for PostgreSQL.

          Can you post minimal code that reproduces the problem? - I'm happy to test against mysql.

      See the first part of my post. I put the Perl code up as well as the definition for the location table. The person table (the one I was actually intersted in populating in this case) couldn't be a simpler table.

      create table person ( person_id SERIAL not null primary key, given_name text not null, surname text not null, email_addr text not null default 'no@email.net' );


      Peter L. Berghold -- Unix Professional
      Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

        Well, if you post minimal code that reproduces the problem, I can try and test it against mysql, if you don't, I can't.

        I can't reconstruct a program that reproduces the problem from snippets, since I don't have postgresql, and therefore have no way of knowing whether such a reconstructed program would trigger the bug or not against postresql - which would make it a pointless exercise.

        Tom Melly, tom@tomandlu.co.uk