Re: [Dovecot] expire plugin: columns not uniq

2009-08-31 Thread Nikita Koshikov
On Mon, 24 Aug 2009 13:33:15 -0400
Timo Sirainen t...@iki.fi wrote:

 On Mon, 2009-08-24 at 13:27 -0400, Timo Sirainen wrote:
   CREATE TRIGGER mergeexpire BEFORE INSERT ON expires FOR EACH ROW
   BEGIN 
 UPDATE expires SET expire_stamp=NEW.expire_stamp 
 WHERE username = NEW.username AND mailbox = NEW.mailbox; 
 SELECT raise(ignore) 
 WHERE (SELECT 1 FROM expires WHERE username = NEW.username AND 
   mailbox = NEW.mailbox) IS NOT NULL;
   END;
   
   This seem some kind crudely to me, but it's working.
  
  That looks correct to me. 
 

Sorry for such lately response, I have just returned from vacation.

 Oh, except there's a small race condition if the first row is being
 added at the same time by two processes. That's why the PostgreSQL
 trigger is so much more complex. But it should be somewhat rare I
 guess..
 
 Unless SQLite has some locks that prevent that? Anyway I was thinking
 that two processes run the UPDATE part of the trigger and then both try
 to INSERT. One of them succeeds and the other one fails. But the row
 gets added anyway and the timestamp is the same anyway, so it probably
 doesn't matter all that much, just logs an error.

As far as I know, sqlite permits to write database changes(INSERT,UPDATE or 
DELETE) to only 1 process at the same time and when process is updating data - 
sqlite table is locking. This might be OS queue processing, because  sqlite 
have no master process for handling such racing. In my understanding, if two 
identical INSERTs will be passed to database(and the record already exists) - 
trigger's UPDATE will be run twice, but consistently.
My admissions can be faulty and sqlite experts should shed some light on this 
situation.
The above trigger is working about a week in my setup - I have checked error 
log for this period - there is nothing related to database issues.


Re: [Dovecot] expire plugin: columns not uniq

2009-08-24 Thread Timo Sirainen
On Fri, 2009-08-21 at 17:02 +0300, Nikita Koshikov wrote:
  Search the Wiki about Postgres and the requirement of a TRIGGER.
  I guess that sqlite requires something like this.
 
 Maybe someone family with sqlite will say how to make this trigger better and 
 constrain check field existence before doing UPDATE
 
 CREATE TRIGGER mergeexpire BEFORE INSERT ON expires FOR EACH ROW
 BEGIN 
   UPDATE expires SET expire_stamp=NEW.expire_stamp 
   WHERE username = NEW.username AND mailbox = NEW.mailbox; 
   SELECT raise(ignore) 
   WHERE (SELECT 1 FROM expires WHERE username = NEW.username AND 
 mailbox = NEW.mailbox) IS NOT NULL;
 END;
 
 This seem some kind crudely to me, but it's working.

That looks correct to me. I'll add it to the wiki page. A similar
trigger could be used for dict quota too. So now that SQLite is working,
I'll just start deprecating Berkeley DB support even more strongly.
Thanks. :)



signature.asc
Description: This is a digitally signed message part


Re: [Dovecot] expire plugin: columns not uniq

2009-08-24 Thread Timo Sirainen
On Mon, 2009-08-24 at 13:27 -0400, Timo Sirainen wrote:
  CREATE TRIGGER mergeexpire BEFORE INSERT ON expires FOR EACH ROW
  BEGIN 
  UPDATE expires SET expire_stamp=NEW.expire_stamp 
  WHERE username = NEW.username AND mailbox = NEW.mailbox; 
  SELECT raise(ignore) 
  WHERE (SELECT 1 FROM expires WHERE username = NEW.username AND 
  mailbox = NEW.mailbox) IS NOT NULL;
  END;
  
  This seem some kind crudely to me, but it's working.
 
 That looks correct to me. 

Oh, except there's a small race condition if the first row is being
added at the same time by two processes. That's why the PostgreSQL
trigger is so much more complex. But it should be somewhat rare I
guess..

Unless SQLite has some locks that prevent that? Anyway I was thinking
that two processes run the UPDATE part of the trigger and then both try
to INSERT. One of them succeeds and the other one fails. But the row
gets added anyway and the timestamp is the same anyway, so it probably
doesn't matter all that much, just logs an error.


signature.asc
Description: This is a digitally signed message part


Re: [Dovecot] expire plugin: columns not uniq

2009-08-21 Thread Steffen Kaiser

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On Wed, 19 Aug 2009, Nikita Koshikov wrote:


How can I solve this ? and why expire plugin is trying to use INSERT, instead 
of UPDATE ?


Search the Wiki about Postgres and the requirement of a TRIGGER.
I guess that sqlite requires something like this.

Unfortunately, there is no UPDATE OR INSERT in SQL and it is hard to 
simulate.


Bye,

- -- 
Steffen Kaiser

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.6 (GNU/Linux)

iQEVAwUBSo5fbnWSIuGy1ktrAQKQdQgAs1fioq/x86JNb9L7SvGnU9wPOUICilsI
RcY+PrsMzGxdRShlnDhEIJGRlbzr7jHDhDhMfej+TGP9XqBFPqBphVxT8JIJmGXz
Z4qEvwLoyuSKxWikLxVLaslDPYPu2tjmvKt+HWaLgev7ecwFF8NoKBHhWV6fR3x9
o/xVVcj6hM38SkiGc6+t27OC5ch6Tq5Vqmau4QIB7fkN8bA8IoBU17rM0eW4k80m
7nKTVsPqFcDKlmes2d5vJVlCYg+NCy69RVIZEFQwOJahBjveSvJsXWnhks9e0nEk
PmtMPMUFHOvfe+4KfK2GFxAPCznOSrxfgMuUewXnENCgLtXrox+zPA==
=8vpx
-END PGP SIGNATURE-


Re: [Dovecot] expire plugin: columns not uniq

2009-08-21 Thread Nikita Koshikov
On Fri, 21 Aug 2009 10:48:42 +0200 (CEST)
Steffen Kaiser skdove...@smail.inf.fh-brs.de wrote:

 -BEGIN PGP SIGNED MESSAGE-
 Hash: SHA1
 
 On Wed, 19 Aug 2009, Nikita Koshikov wrote:
 
  How can I solve this ? and why expire plugin is trying to use INSERT, 
  instead of UPDATE ?
 
 Search the Wiki about Postgres and the requirement of a TRIGGER.
 I guess that sqlite requires something like this.

Thank for your answer.
I'll dig in this direction.
 
 Unfortunately, there is no UPDATE OR INSERT in SQL and it is hard to 
 simulate.

You mean in dovecot expire plugin or where ?

 
 Bye,
 
 - -- 
 Steffen Kaiser
 -BEGIN PGP SIGNATURE-
 Version: GnuPG v1.4.6 (GNU/Linux)
 
 iQEVAwUBSo5fbnWSIuGy1ktrAQKQdQgAs1fioq/x86JNb9L7SvGnU9wPOUICilsI
 RcY+PrsMzGxdRShlnDhEIJGRlbzr7jHDhDhMfej+TGP9XqBFPqBphVxT8JIJmGXz
 Z4qEvwLoyuSKxWikLxVLaslDPYPu2tjmvKt+HWaLgev7ecwFF8NoKBHhWV6fR3x9
 o/xVVcj6hM38SkiGc6+t27OC5ch6Tq5Vqmau4QIB7fkN8bA8IoBU17rM0eW4k80m
 7nKTVsPqFcDKlmes2d5vJVlCYg+NCy69RVIZEFQwOJahBjveSvJsXWnhks9e0nEk
 PmtMPMUFHOvfe+4KfK2GFxAPCznOSrxfgMuUewXnENCgLtXrox+zPA==
 =8vpx
 -END PGP SIGNATURE-


Re: [Dovecot] expire plugin: columns not uniq

2009-08-21 Thread Nikita Koshikov
 Search the Wiki about Postgres and the requirement of a TRIGGER.
 I guess that sqlite requires something like this.

Maybe someone family with sqlite will say how to make this trigger better and 
constrain check field existence before doing UPDATE

CREATE TRIGGER mergeexpire BEFORE INSERT ON expires FOR EACH ROW
BEGIN 
UPDATE expires SET expire_stamp=NEW.expire_stamp 
WHERE username = NEW.username AND mailbox = NEW.mailbox; 
SELECT raise(ignore) 
WHERE (SELECT 1 FROM expires WHERE username = NEW.username AND 
mailbox = NEW.mailbox) IS NOT NULL;
END;

This seem some kind crudely to me, but it's working.


Re: [Dovecot] expire plugin: columns not uniq

2009-08-21 Thread Steffen Kaiser

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On Fri, 21 Aug 2009, Nikita Koshikov wrote:


You mean in dovecot expire plugin or where ?


No, in general.
If one wants some data in a DB, but update if already present.

If you re-programm the TRIGGER in the client, you need to lock the whole 
table, if you want to overcome all race conditions and also don't want any 
errors logged (at least with postgres).


Bye,

- -- 
Steffen Kaiser

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.6 (GNU/Linux)

iQEVAwUBSo62cHWSIuGy1ktrAQLimQf/QYdrEX3y94bK1jmMk4T+bIIMcjmzESe5
0o+W0AFSOifWop8JOHZy1YJUXa5gkGnhg09ar0zC9UQ8T4J97xz0ORfe3UHmisKv
xh2zJ8lhw1OviQ4qrPcSot1/D/SQ/xdPKbBaaD1S7k+E0zK44P74PHGAvRsx+tUZ
3BR0U73LFtAiAhvW/y2rseo/vIuXBBSPthBK/nExiiODN9P9Vq3iOczfZwVUkVmo
cNwArCwjkBGk6dGRnfGEoPKWsa/qFVHqQPjwen7j0T2ak58Vfm9Vc3pGmMSequGh
MIjcOHcmpcF6AAhsZQIoYewgVtQQ+aXY9T4zQo6JbLCEyF7RCs/yRg==
=cinD
-END PGP SIGNATURE-


Re: [Dovecot] expire plugin: columns not uniq

2009-08-21 Thread Nikita Koshikov
No, in general.

 If one wants some data in a DB, but update if already present.

 If you re-programm the TRIGGER in the client, you need to lock the whole
 table, if you want to overcome all race conditions and also don't want any
 errors logged (at least with postgres).


Thanks for explanation.
I'm not so aware in databases, but if trigger will be programmed on client
side - this will make code more portable(in case of database choicing) and
what is the less evil -  locking or portability...
In any case, thanks for reply, it helps me much.


[Dovecot] expire plugin: columns not uniq

2009-08-19 Thread Nikita Koshikov

Hello list,

My dovecot setup have expire plugin enabled. It is working fine: new records 
added to database(sqlite), expire-tool successfully expunges old mail, but when 
expire-tool try to update database record for processed user, I get error in 
logs:

r...@mail dovecot 0:0 # /usr/sbin/dovecot --exec-mail ext 
/usr/libexec/dovecot/expire-tool.sh --test
Info: koshiko...@domain.com/Spam: timestamp 1250622406 (Tue Aug 18 22:06:46 
2009) - 1250684287 (Wed Aug 19 15:18:07 2009)


in logs:
Aug 19 13:29:11 dict: Error: sqlite: exec(INSERT INTO expires 
(expire_stamp,username,mailbox) VALUES 
('1250684287','koshiko...@domain.com','Spam')) failed: columns username, 
mailbox are not unique (19)
Aug 19 13:29:11 dict: Error: sql dict: commit failed: 1҅�t+�]�Ћu�}��]Ð�t


This is my expire dict config file:

connect = /var/mail/expire.db
#v1.2
map {
pattern = shared/expire/$user/$mailbox
table = expires
value_field = expire_stamp

fields {
username = $user
mailbox = $mailbox
}
}

expire plugin related dovecot sections:
dict {
  expire = sqlite:/etc/dovecot/plugins/expire.conf
}
plugin {
  expire = Trash 30 Spam 20
  expire_dict = proxy::expire
}

Version of sqlite is 3.6.16, dovecot-1.2.3.

How can I solve this ? and why expire plugin is trying to use INSERT, instead 
of UPDATE ?