On Wed, 2005-02-23 at 11:04 +0100, Paul J Stevens wrote:
> I've been building and testing debian packages with sqlite support with the
> imap
> test-suite in test-scripts/.
>
> The testFetch fails until there are enough testmessages in the
> dbmail_messages
> table. After there are at least 10 messages (10 failure runs of the test),
> that
> one works just fine.
>
> But the test-suite encounters one problem with uniqueness constraints for
> SETACL.
>
>
> sqlite> select * from dbmail_acl;
> 3|3|0|0|0|0|0|0|0|0|0
> sqlite> UPDATE dbmail_acl SET lookup_flag = '1' WHERE user_id = '3' AND
> mailbox_id = '3';
> SQL error: UNIQUEness constraint violation
>
> Shouldn't below trigger read "...foo.a > 1..." ??
No. That would be wrong.
I read it to say, "when the count of dbmail_acl.user_id ##
dbmail_acl.mailbox_id matching the attempting-to-update (new)
new.user_id ## new.mailbox_id is above ZERO" - and that's what it should
be...
$ sqlite dbmail-sqlite.db
sqlite> insert into dbmail_acl (user_id,mailbox_id) values('1','2');
sqlite> insert into dbmail_acl (user_id,mailbox_id) values('1','2');
SQL error: UNIQUEness constraint violation
sqlite> insert into dbmail_acl (user_id,mailbox_id) values('1','3');
sqlite> insert into dbmail_acl (user_id,mailbox_id) values('2','2');
sqlite> insert into dbmail_acl (user_id,mailbox_id) values('2','3');
sqlite> insert into dbmail_acl (user_id,mailbox_id) values('2','3');
SQL error: UNIQUEness constraint violation
sqlite> update dbmail_acl set user_id='2' where user_id='1';
SQL error: UNIQUEness constraint violation
sqlite> update dbmail_acl set user_id='4' where user_id='1';
That's what I expect. But additionally, you're seeing:
sqlite> delete from dbmail_acl;
sqlite> insert into dbmail_acl(user_id,mailbox_id) values('3','3');
sqlite> update dbmail_acl set lookup_flag='1' where user_id='3' and
mailbox_id='3';
SQL error: UNIQUEness constraint violation
And that's wrong. We need it to say "when the count of .... matching
the .... AND we're actually changing the user_id or mailbox_id"
The constraint should be:
CREATE TRIGGER dbmail_acl_constraint_update
BEFORE UPDATE ON dbmail_acl
BEGIN
SELECT CASE WHEN foo.a > 0 THEN RAISE(ROLLBACK, 'UNIQUEness
constraint violation')
ELSE 1 END FROM (
SELECT COUNT(*) AS a FROM dbmail_acl
WHERE new.user_id = dbmail_acl.user_id
AND new.mailbox_id = dbmail_acl.mailbox_id
AND new.rowid != dbmail_acl.mailbox_id -- NOTE here
) AS foo;
END;
I've attached a corrected create_tables.sql
--
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/
-- Copyright (C) 2005 Internet Connection, Inc.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either
-- version 2 of the License, or (at your option) any later
-- version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-- $Id: create_tables.mysql,v 1.32 2004/10/31 12:16:17 aaron Exp $
BEGIN TRANSACTION;
CREATE TABLE dbmail_aliases (
alias_idnr INTEGER PRIMARY KEY,
alias TEXT NOT NULL,
deliver_to TEXT NOT NULL,
client_idnr INTEGER DEFAULT '0' NOT NULL
);
CREATE INDEX dbmail_aliases_index_1 ON dbmail_aliases(alias);
CREATE INDEX dbmail_aliases_index_2 ON dbmail_aliases(client_idnr);
CREATE TABLE dbmail_users (
user_idnr INTEGER PRIMARY KEY,
userid TEXT NOT NULL,
passwd TEXT NOT NULL,
client_idnr INTEGER DEFAULT '0' NOT NULL,
maxmail_size INTEGER DEFAULT '0' NOT NULL,
curmail_size INTEGER DEFAULT '0' NOT NULL,
encryption_type TEXT DEFAULT '' NOT NULL,
last_login DATETIME DEFAULT '1979-11-03 22:05:58' NOT NULL
);
CREATE UNIQUE INDEX dbmail_users_1 ON dbmail_users(userid);
CREATE TABLE dbmail_mailboxes (
mailbox_idnr INTEGER PRIMARY KEY,
owner_idnr INTEGER DEFAULT '0' NOT NULL,
name TEXT BINARY NOT NULL,
seen_flag BOOLEAN default '0' not null,
answered_flag BOOLEAN default '0' not null,
deleted_flag BOOLEAN default '0' not null,
flagged_flag BOOLEAN default '0' not null,
recent_flag BOOLEAN default '0' not null,
draft_flag BOOLEAN default '0' not null,
no_inferiors BOOLEAN default '0' not null,
no_select BOOLEAN default '0' not null,
permission BOOLEAN default '2'
);
CREATE INDEX dbmail_mailboxes_1 ON dbmail_mailboxes(name);
CREATE INDEX dbmail_mailboxes_2 ON dbmail_mailboxes(owner_idnr);
CREATE UNIQUE INDEX dbmail_mailboxes_3 ON dbmail_mailboxes(owner_idnr,name);
CREATE TABLE dbmail_subscription (
user_id INTEGER NOT NULL,
mailbox_id INTEGER NOT NULL
);
CREATE TRIGGER dbmail_subscription_constraint_insert
BEFORE INSERT ON dbmail_subscription
BEGIN
SELECT CASE WHEN foo.a > 0 THEN RAISE(ROLLBACK, 'UNIQUEness
constraint violation')
ELSE 1 END FROM (
SELECT COUNT(*) AS a FROM dbmail_subscription
WHERE new.user_id = dbmail_subscription.user_id
AND new.mailbox_id = dbmail_subscription.mailbox_id
AND new.rowid != dbmail_subscription.rowid
) AS foo;
END;
CREATE TRIGGER dbmail_subscription_constraint_update
BEFORE UPDATE ON dbmail_subscription
BEGIN
SELECT CASE WHEN foo.a > 0 THEN RAISE(ROLLBACK, 'UNIQUEness
constraint violation')
ELSE 1 END FROM (
SELECT COUNT(*) AS a FROM dbmail_subscription
WHERE new.user_id = dbmail_subscription.user_id
AND new.mailbox_id = dbmail_subscription.mailbox_id
AND new.rowid != dbmail_subscription.rowid
) AS foo;
END;
CREATE TABLE dbmail_acl (
user_id INTEGER NOT NULL,
mailbox_id INTEGER NOT NULL,
lookup_flag BOOLEAN default '0' not null,
read_flag BOOLEAN default '0' not null,
seen_flag BOOLEAN default '0' not null,
write_flag BOOLEAN default '0' not null,
insert_flag BOOLEAN default '0' not null,
post_flag BOOLEAN default '0' not null,
create_flag BOOLEAN default '0' not null,
delete_flag BOOLEAN default '0' not null,
administer_flag BOOLEAN default '0' not null
);
CREATE TRIGGER dbmail_acl_constraint_insert
BEFORE INSERT ON dbmail_acl
BEGIN
SELECT CASE WHEN foo.a > 0 THEN RAISE(ROLLBACK, 'UNIQUEness
constraint violation')
ELSE 1 END FROM (
SELECT COUNT(*) AS a FROM dbmail_acl
WHERE new.user_id = dbmail_acl.user_id
AND new.mailbox_id = dbmail_acl.mailbox_id
AND new.rowid != dbmail_acl.rowid
) AS foo;
END;
CREATE TRIGGER dbmail_acl_constraint_update
BEFORE UPDATE ON dbmail_acl
BEGIN
SELECT CASE WHEN foo.a > 0 THEN RAISE(ROLLBACK, 'UNIQUEness
constraint violation')
ELSE 1 END FROM (
SELECT COUNT(*) AS a FROM dbmail_acl
WHERE new.user_id = dbmail_acl.user_id
AND new.mailbox_id = dbmail_acl.mailbox_id
AND new.rowid != dbmail_acl.rowid
) AS foo;
END;
CREATE TABLE dbmail_physmessage (
id INTEGER PRIMARY KEY,
messagesize INTEGER DEFAULT '0' NOT NULL,
rfcsize INTEGER DEFAULT '0' NOT NULL,
internal_date DATETIME default '0' not null
);
CREATE TABLE dbmail_messages (
message_idnr INTEGER PRIMARY KEY,
mailbox_idnr INTEGER DEFAULT '0' NOT NULL,
physmessage_id INTEGER DEFAULT '0' NOT NULL,
seen_flag BOOLEAN default '0' not null,
answered_flag BOOLEAN default '0' not null,
deleted_flag BOOLEAN default '0' not null,
flagged_flag BOOLEAN default '0' not null,
recent_flag BOOLEAN default '0' not null,
draft_flag BOOLEAN default '0' not null,
unique_id TEXT NOT NULL,
status BOOLEAN unsigned default '0' not null
);
CREATE INDEX dbmail_messages_1 ON dbmail_messages(mailbox_idnr);
CREATE INDEX dbmail_messages_2 ON dbmail_messages(physmessage_id);
CREATE INDEX dbmail_messages_3 ON dbmail_messages(seen_flag);
CREATE INDEX dbmail_messages_4 ON dbmail_messages(unique_id);
CREATE INDEX dbmail_messages_5 ON dbmail_messages(status);
CREATE INDEX dbmail_messages_6 ON dbmail_messages(mailbox_idnr,status);
CREATE TABLE dbmail_messageblks (
messageblk_idnr INTEGER PRIMARY KEY,
physmessage_id INTEGER DEFAULT '0' NOT NULL,
messageblk TEXT NOT NULL,
blocksize INTEGER DEFAULT '0' NOT NULL,
is_header BOOLEAN DEFAULT '0' NOT NULL
);
CREATE INDEX dbmail_messageblks_1 ON dbmail_messageblks(physmessage_id);
CREATE INDEX dbmail_messageblks_2 ON dbmail_messageblks(physmessage_id,
is_header);
CREATE TABLE dbmail_auto_notifications (
user_idnr INTEGER PRIMARY KEY,
notify_address VARCHAR(100)
);
CREATE TABLE dbmail_auto_replies (
user_idnr INTEGER PRIMARY KEY,
reply_body TEXT
);
CREATE TABLE dbmail_pbsp (
idnr INTEGER PRIMARY KEY,
since DATETIME default '0' not null,
ipnumber TEXT NOT NULL
);
CREATE UNIQUE INDEX dbmail_pbsp_1 ON dbmail_pbsp(ipnumber);
CREATE INDEX dbmail_pbsp_2 ON dbmail_pbsp(since);
CREATE TABLE dbmail_sievescripts (
owner_idnr INTEGER DEFAULT '0' NOT NULL,
name TEXT NOT NULL,
script TEXT,
active BOOLEAN default '0' not null
);
CREATE INDEX dbmail_sievescripts_1 ON dbmail_sievescripts(name);
CREATE INDEX dbmail_sievescripts_2 ON dbmail_sievescripts(owner_idnr);
CREATE INDEX dbmail_sievescripts_3 ON dbmail_sievescripts(owner_idnr,name);
-- create the user for the delivery chain
INSERT INTO dbmail_users (userid, passwd, encryption_type)
VALUES ('[EMAIL PROTECTED]@__', '', 'md5');
-- insert the 'anyone' user which is used for ACLs.
INSERT INTO dbmail_users (userid, passwd, encryption_type)
VALUES ('anyone', '', 'md5');
COMMIT;