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

Greetings all,

Update: sub-classing from Class::DBI::Pg, as suggested, doesn't solve the issue - the only way that I'm going to fix this is by using before_create and after_create 'triggers'. I'll try that now.

The reason for this behaviour appears to be because Class::DBI isn't that comfortable with Views.

I'm creating a database using Class::DBI and postgres. The postgres primary keys are of postgres datatype 'SERIAL', which is a sequence. On each 'INSERT' postgres auto-increments the sequence and inserts the new number as a primary key. So far so easy.

However, Class::DBI wants to take control of this process. If a column is declared as a primary key and the sequence is declared as a sequence e.g.:

__PACKAGE__->sequence('identity_identity_id_seq');

Then Class::DBI wants to get the next val itself. This has the effect of calling postgres's nextval('identity_identity_id_seq') function. This increments the sequence returning the next value. Class::DBI stores this value (call it 'n').

Class::DBI then asks postgres to insert the row. Postgres increments the sequence again to get the new unique id. The row is inserted with primary key n+1.

Class::DBI returns what it thinks is the new primary key, n, and tries to repopulate its datastructure from the db. Of course it can't, beause there is no row with a primary key 'n'.

I need to stop this behaviour. Ideally I'd like Class::DBI not to try to increment the sequence - and then to return the new primary key id, by doing something like calling postgres's currval function and repopulating its datastructure with that value

One way is to not declare a sequence and to use Class::DBI's after_create and before_create triggers to force the behaviour I want. However, this seems messy to me.

Is there a better, easy more logical way of getting a consistent behaviour?

TIA

Replies are listed 'Best First'.
Re: Odd Class::DBI sequence behaviour
by perrin (Chancellor) on Jan 23, 2005 at 15:53 UTC
    Lots of people are successfully using Class::DBI with Pg. I can't believe something this basic is broken. I suggest you ask this question on the Class::DBI list, posting your code and the relevant parts of your schema. You should not need to do anything special for something so simple.
Re: Odd Class::DBI sequence behaviour
by Corion (Patriarch) on Jan 23, 2005 at 11:40 UTC

    Class::DBI doesn't want to take control of creating new primary keys, if you use the proper subclass, in your case Class::DBI::Pg. That way, if you leave out a primary key, it assumes that the database will fill it in.

      Sub-classing from Class::DBI::Pg doesn't change this behaviour at all. And because of my particular setup using the 'set_up_table' method, doesn't work either. But I'm starting to think that this is because my tables are 'non-standard'.
        worst come to worst, do a passthrough SQL...and don't try to populate that primary key value
        the hardest line to type correctly is: stty erase ^H
Re: Odd Class::DBI sequence behaviour
by zby (Vicar) on Jan 23, 2005 at 19:29 UTC
    If you define the primary key as integer instead of serial Class::DBI would populate it itself and the database would not brake it. You could add default nextval('identity_identity_id_seq') so that non Class::DBI code could use the same sequence.
Re: Odd Class::DBI sequence behaviour
by Anonymous Monk on Apr 16, 2011 at 13:22 UTC
    it's not odd at all, it's doing exactly what your telling it to do. solution is to either not try to set the value your self and just let CDBI do the insert, or if you must absolutely know the value of the id before you insert, change the table id column to remove the default value, and set up your own sequence. Now you can ask for the nextval, incrementing the sequence +1, then do your insert without Pg re-incrementing it.