Hue-Bond has asked for the wisdom of the Perl Monks concerning the following question:

Good localtime :^)

I'm doing a program that uses Class::DBI as the database abstraction. Everything was ok until I began to delete things from the DB. This is the problem I'm facing:

$ perl main.pl enter pg pass: foo (7/2006-11-20) DBD::Pg::st execute failed: called with 1 bind variables when 2 are ne +eded [for Statement "SELECT param2, name, param1, description, param4 +, param5, data2, id, param3 FROM ppo_data WHERE id_attached=? AND date=? " with ParamValues: 1=undef, 2=undef] at /usr/share/perl5/DBIx/Context +ualFetch.pm line 52, <STDIN> line 1.

I'm able to reproduce the problem with this:

postgresql> CREATE TABLE "indicators" ( id SERIAL UNIQUE, name VARCHAR(20) NOT NULL, param1 VARCHAR(10), param2 VARCHAR(10), param3 VARCHAR(10), param4 VARCHAR(10), param5 VARCHAR(10), description VARCHAR(30), PRIMARY KEY (id) ); postgresql> INSERT INTO indicators VALUES (7, 'PPO', 9, 4, 2, NULL, NU +LL, 'PPO'); postgresql> CREATE TABLE "ppo_data" ( id_attached INTEGER, date DATE NOT NULL, data1 NUMERIC(10, 5) NOT NULL, data2 NUMERIC(10, 5), PRIMARY KEY (id_attached, date) ); postgresql> INSERT INTO ppo_data VALUES (7, '20061120', 23, 34);
## FOO.pm package FOO; use base 'Class::DBI'; my $username = 'hue'; my $password; my $pgdbhost = 'localhost'; my $pgdbname = 'hue'; sub get_pgdbpass { print "enter pg pass: "; ## cheap system '/bin/stty -echo'; chomp (my $pgdbpass = <STDIN>); system '/bin/stty echo'; print "\n"; return $pgdbpass; } __PACKAGE__->connection ( "dbi:Pg:dbname=$pgdbname;host=$pgdbhost;", $username, $password ? $password : ($password = get_pgdbpass), {AutoCommit => 0, RaiseError => 1}, ); 1;
## FOO/Indicators.pm package FOO::Indicators; use base 'FOO'; __PACKAGE__->table ('indicators'); __PACKAGE__->columns ( All => qw/id name param1 param2 param3 param4 param5 description/ ); 1;
## FOO/Indicators/PPO.pm package FOO::Indicators::PPO; use base 'FOO::Indicators'; __PACKAGE__->table ('ppo_data'); __PACKAGE__->columns (Primary => qw/id_attached date/); __PACKAGE__->columns (Essential => qw/data1/); __PACKAGE__->columns (Others => qw/data2/); 1;
## main.pl use warnings; use strict; use FOO::Indicators::PPO; my $foo = FOO::Indicators::PPO->retrieve (id_attached => 7, date => '2 +0061120'); print "foo ($foo)\n"; $foo->delete; FOO::Indicators::PPO->dbi_commit;

Since there are no relationships at all (neither in the database nor in the Class::DBI objects) I don't understand why so many fields are being fetched in the SQL query that is shown in the error message. I also tried ->search()->delete_all instead of ->retrieve()->delete but found the same problem. Was able to remove by using delete as a class method but that's deprecated and I'd like to do things the right way.

--
David Serrano

Replies are listed 'Best First'.
Re: Problem when deleting Class::DBI objects
by rhesa (Vicar) on Nov 26, 2007 at 15:12 UTC
    Don't let FOO::Indicators::PPO inherit from FOO::Indicators, but make it a subclass of Foo. Your current structure gives PPO all the columns of Indicators as well, which is not what you expected.

    You generally don't want to subclass actual table classes, unless you have a very specific reason to (and I can't even think of any off the top of my head).

Re: Problem when deleting Class::DBI objects
by CountZero (Bishop) on Nov 26, 2007 at 23:01 UTC
    Not an answer to your question, but just a remark: Did you consider using DBIX::Class instead of Class::DBI? I find DBIX::Class better documented and generally easier to use.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Don't let FOO::Indicators::PPO inherit from FOO::Indicators, but make it a subclass of Foo.

      Thanks! That did it, but now I have a new question: what happens with the methods I had in FOO::Indicators? I tried moving them to FOO and it works but I guess there's a better solution.

      Did you consider using DBIX::Class instead of Class::DBI?

      The truth is that I didn't. I found Class::DBI when searching for something, and then I didn't know that there were more modules available for that. Maybe in a future rewrite...

      --
      David Serrano