Unexplained behaviour - Mailing list pgsql-general
From | Jean-Christophe Boggio |
---|---|
Subject | Unexplained behaviour |
Date | |
Msg-id | 4355277705.20010329011301@thefreecat.org Whole thread Raw |
Responses |
Re: Unexplained behaviour
|
List | pgsql-general |
Hi, I have a before-ins-row trigger that is supposed to find a unique value for one of the fields but it seems sometimes there are non-unique values that try to be created. They are rejected but I don't see the bug. 50000 user accounts were created with this code but we seem to have a few that fail and we don't understand how it's possible if concurrency is not involved. Hope someone can help... Here's the trigger : ===== drop function trig_identite_befinsrow(); create function trig_identite_befinsrow() returns opaque as ' declare n int4; n1 int4; n2 int4; i int4; c int4; s text; begin -- create a unique 12 byte long field (IDMEMBRE) starting with '11' then -- 8 chars = minutes since 01/01/2000 then a 2-byte key with -- some silly algorithm of mine ;-) select reltime(now()-''january 1, 2000'')::int into n; n:=n/60; loop -- calculate key n1 := 0; s := ''11''||lpad(n,8,''0''); for i in 1..10 loop if i=1 then n2:=2; end if; if i=2 then n2:=3; end if; if i=3 then n2:=5; end if; if i=4 then n2:=7; end if; if i=5 then n2:=11; end if; if i=6 then n2:=13; end if; if i=7 then n2:=17; end if; if i=8 then n2:=19; end if; if i=9 then n2:=23; end if; if i=10 then n2:=29; end if; n1:=n1::int+(substr(s,i,1)::int+1)::int*n2; end loop; n1:=n1 % 100; s:=s||lpad(n1,2,''0''); -- already exists ? select count(IDMEMBRE) into c from identite where IDMEMBRE=s; -- no, it's fine if c=0 then new.idmembre:=s; return new; exit; end if; -- if we get here, the key already exists n := n-1; end loop; new.idmembre := s; return new; end; ' language 'plpgsql'; drop trigger trig_identite_befinsrow on identite; create trigger trig_identite_befinsrow before insert on identite for each row execute procedure trig_identite_befinsrow(); ===== Now, the table's definition : ===== mydb@miaou# \d identite Table "identite" Attribute | Type | Modifier -----------+---------+---------- idmembre | text | not null login | text | passe | text | actif | char(1) | email | text | miles | integer | Indices: actif_identite_key, email_identite_key, identite_pkey, login_identite_key, miles_identite_key, passe_identite_key mydb@miaou# \d identite_pkey Index "identite_pkey" Attribute | Type -----------+------ idmembre | text unique btree (primary key) ===== And here are the logs I get. I provide them as-is so that you can see there does not seem to be 2 triggers running at the same time. Unfortunately, there are other queries being executed at the same time but they don't interfere (hope so). NB: The first line is the insert command that triggers the trigger. ===== query: insert into identite (login,passe,actif,email,miles) values ('someone','123456','O','someone@somemail.com',0) ProcessQuery query: SELECT reltime(now()-'january 1, 2000')::int StartTransactionCommand query: select lower(urlpartenaire) from refererpartenaire where lower(urlpartenaire)=lower('perso.jobscout24.fr') CommitTransactionCommand ProcessQuery CommitTransactionCommand query: SELECT $1 /60 StartTransactionCommand query: SELECT idcondition FROM conditions c,partenaires p WHERE c.nompartenaire=p.nompartenaire AND p.nomcache='hjklfhgklsjg' AND c.nomcondition='macondition' ProcessQuery CommitTransactionCommand StartTransactionCommand query: SELECT m.OID FROM cpt_maxibanner m WHERE datebanner=date('now') AND idcondition=1447 AND membre='N' ProcessQuery StartTransactionCommand query: select idmembre from identite where login='marseilliais' ProcessQuery CommitTransactionCommand query: SELECT 0 query: SELECT '11'||lpad( $1 ,8,'0') query: SELECT 1 query: SELECT 10 query: SELECT $1 =1 query: SELECT 2 query: SELECT $1 =2 query: SELECT $1 =3 query: SELECT $1 =4 query: SELECT $1 =5 query: SELECT $1 =6 query: SELECT $1 =7 query: SELECT $1 =8 query: SELECT $1 =9 query: SELECT $1 =10 query: SELECT $1 ::int+(substr( $2 , $3 ,1)::int+1)::int* $4 query: SELECT 3 query: SELECT 5 query: SELECT 7 query: SELECT 11 query: SELECT 13 query: SELECT 17 query: SELECT 19 query: SELECT 23 query: SELECT 29 query: SELECT $1 % 100 query: SELECT $1 ||lpad( $2 ,2,'0') query: SELECT count(IDMEMBRE) from identite where IDMEMBRE= $1 query: SELECT $1 =0 query: SELECT $1 -1 query: SELECT $1 StartTransactionCommand query: insert into prefs (idmembre,transinfopart,questionperso,reponseperso,fromsite,abonewsletter) values ('110065208528','O','','reum','yd3X4URQSdfG','O') ProcessQuery ERROR: Cannot insert a duplicate key into unique index identite_pkey -- Jean-Christophe Boggio cat@thefreecat.org Independant Consultant and Developer Delphi, Linux, Perl, PostgreSQL
pgsql-general by date: