Re: A problem with sequences... - Mailing list pgsql-general

From Richard Huxton
Subject Re: A problem with sequences...
Date
Msg-id 200302201928.17285.dev@archonet.com
Whole thread Raw
In response to Re: A problem with sequences...  (Dima Tkach <dmitry@openratings.com>)
Responses Re: A problem with sequences...  (Dmitry Tkach <dmitry@openratings.com>)
List pgsql-general
On Thursday 20 Feb 2003 2:56 pm, Dima Tkach wrote:
> >Before looking into more obscure possibilities, are you using the sequence
> > to generate these explicit id's? If not, that's why you're getting
> > duplicates, the sequence generator doesn't know you've used these
> > numbers.
>
> Yeah... I understand this.
> In this case, the id is *never* specified explicitly. Java app either
> knows the id or it does not.
> If it knows it, it does the update, otherwise, it does an insert, with
> *no* id specified, and gets the new id back from that rule, so that time
> it will
> know the id and end up doing update...
>
> I was referring to the situation in general when somehow (like data
> migration) the id is specified, I just don't want that rule to barf. It
> is definitely not what's causing my problem. So, let's get into those
> 'obscure possibilities' now :-)

Well, in that case you need to setval() the sequence to something bigger than
any used numbers after the import.

OK - let's look at the rule:

create table answer
(
    id    serial primary key,
    data  text
);

create rule answer_id_seq as on insert to answer do select coalesce (new.id,
last_value) as id from answer_id_seq;

Well - you're going to have problems if you do something like:

INSERT INTO answer (data) (SELECT d FROM foo);

I daresay you're not, but something to bear in mind.

To see why you're getting problems with duplicate ID numbers, open two psql
windows and do:

1> SELECT nextval('answer_id_seq');
2> SELECT nextval('answer_id_seq');
1> SELECT last_value FROM answer_id_seq;
2> SELECT last_value FROM answer_id_seq;

As you'll see, last_value isn't concurrent-safe like currval() and nextval()
are.

So - if you want to keep your rule, you'll want to rewrite it to use currval()
as you mentioned.

Personally, I'd write a function to insert into the table and make the app use
that, or create a view and have the app insert via that. Getting a result-set
back from an insert would spook me if I wasn't expecting it.
--
  Richard Huxton

pgsql-general by date:

Previous
From: Richard Huxton
Date:
Subject: Re: What is the quickest query in the database?
Next
From: Dmitry Tkach
Date:
Subject: Re: A problem with sequences...