
-- This script fixes the 2.1 database schema for use with 3.0
-- Running this script will drop legacy caching tables,
-- so backup your database before continuing!

SET FOREIGN_KEY_CHECKS=0;

DROP PROCEDURE IF EXISTS dodropkeys;
DELIMITER //
CREATE PROCEDURE dodropkeys()
BEGIN
mainloop: LOOP
  SELECT TABLE_NAME, CONSTRAINT_NAME INTO @droptable, @dropkey FROM information_schema.KEY_COLUMN_USAGE
  WHERE `REFERENCED_TABLE_SCHEMA` LIKE DATABASE()
  AND `REFERENCED_TABLE_NAME` IS NOT NULL ORDER BY CONSTRAINT_NAME LIMIT 1;
  IF @dropkey IS NULL THEN 
    LEAVE mainloop;
  END IF;
  SET @sqltext := CONCAT('ALTER TABLE ', @droptable,' DROP FOREIGN KEY ', @dropkey);
  PREPARE dropkeys FROM @sqltext;
  EXECUTE dropkeys;
  DEALLOCATE PREPARE dropkeys;
  SET @dropkey = NULL;
END LOOP mainloop;

-- Workaround for different Upgrade pathes
  SELECT index_name INTO @dropkey FROM information_schema.STATISTICS
  WHERE table_schema like DATABASE()
  AND table_name = "dbmail_sievescripts"
  GROUP BY index_name
  HAVING count(1) = 2;

IF @dropkey IS NOT NULL THEN
  SET @sqltext := CONCAT('ALTER TABLE dbmail_sievescripts DROP INDEX ', @dropkey);
  PREPARE dropkeys FROM @sqltext;
  EXECUTE dropkeys;
  DEALLOCATE PREPARE dropkeys;
  SET @dropkey = NULL;
END IF;

END//
DELIMITER ;

CALL dodropkeys();
DROP PROCEDURE IF EXISTS dodropkeys;

-- Make sure our database is set for utf8
ALTER DATABASE CHARACTER SET utf8;

-- Delete old cached data for the references
BEGIN;
DELETE FROM dbmail_referencesfield;
COMMIT;

-- Drop old legacy cache tables
DROP TABLE IF EXISTS dbmail_ccfield;
DROP TABLE IF EXISTS dbmail_datefield;
DROP TABLE IF EXISTS dbmail_fromfield;
DROP TABLE IF EXISTS dbmail_replytofield;
DROP TABLE IF EXISTS dbmail_subjectfield;
DROP TABLE IF EXISTS dbmail_tofield;

-- Empty cache tables
TRUNCATE TABLE dbmail_envelope;

-- create new storage tables
DROP TABLE IF EXISTS `dbmail_mimeparts`;
CREATE TABLE `dbmail_mimeparts` (
        `id`   bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
        `hash` char(128) NOT NULL,
        `data` longblob NOT NULL,
        `size` bigint(20) DEFAULT 0 NOT NULL,
        PRIMARY KEY  (`id`),
        KEY `hash` (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `dbmail_partlists`;
CREATE TABLE `dbmail_partlists` (
  `physmessage_id` bigint(20) UNSIGNED NOT NULL default '0',
  `is_header` tinyint(1) NOT NULL default '0',
  `part_key` smallint(6) NOT NULL default '0',
  `part_depth` smallint(6) NOT NULL default '0',
  `part_order` smallint(6) NOT NULL default '0',
  `part_id` bigint(20) UNSIGNED NOT NULL default '0',
  KEY `physmessage_id` (`physmessage_id`),
  KEY `part_id` (`part_id`),
  UNIQUE KEY `message_parts` (`physmessage_id`,`part_key`,`part_depth`,`part_order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- message meta data
DROP TABLE IF EXISTS dbmail_keywords;
CREATE TABLE dbmail_keywords (
        message_idnr bigint(20) UNSIGNED DEFAULT 0 NOT NULL,
        keyword varchar(255) NOT NULL,
        PRIMARY KEY  (message_idnr,keyword)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Add new delivery sorting filters table
DROP TABLE IF EXISTS dbmail_filters;
CREATE TABLE dbmail_filters (
        user_id      BIGINT(20) UNSIGNED NOT NULL,
        id           BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
        headername   VARCHAR(255) NOT NULL,
        headervalue  VARCHAR(255) NOT NULL,
        mailbox      VARCHAR(255) NOT NULL,
        PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Add new authlog table
DROP TABLE IF EXISTS dbmail_authlog;
CREATE TABLE `dbmail_authlog` (
  `id` bigint(20) UNSIGNED NOT NULL auto_increment,
  `userid` varchar(100) default NULL,
  `service` varchar(32) default NULL,
  `login_time` datetime default NULL,
  `logout_time` datetime default NULL,
  `src_ip` varchar(16) default NULL,
  `src_port` int(11) default NULL,
  `dst_ip` varchar(16) default NULL,
  `dst_port` int(11) default NULL,
  `status` varchar(32) default 'active',
  `bytes_rx` bigint(20) NOT NULL default '0',
  `bytes_tx` bigint(20) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Create new single instance header storage tables
DROP TABLE IF EXISTS dbmail_headername;
CREATE TABLE `dbmail_headername` (
  `id` bigint(20) UNSIGNED NOT NULL auto_increment,
  `headername` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `headername` (`headername`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE if EXISTS dbmail_headervalue;
CREATE TABLE `dbmail_headervalue` (
  `id` bigint(20) UNSIGNED NOT NULL auto_increment,
  `hash` varchar(255) NOT NULL,
  `headervalue` text NOT NULL,
  `sortfield` varchar(255) default NULL,
  `datefield` datetime default NULL,
  PRIMARY KEY  (`id`),
  KEY `hash` (`hash`),
  KEY `headervalue` (`headervalue`(255)),
  KEY `sortfield` (`sortfield`),
  KEY `datefield` (`datefield`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS dbmail_header;
CREATE TABLE `dbmail_header` (
  `physmessage_id` bigint(20) UNSIGNED NOT NULL,
  `headername_id` bigint(20) UNSIGNED NOT NULL,
  `headervalue_id` bigint(20) UNSIGNED NOT NULL,
  PRIMARY KEY  (`physmessage_id`,`headername_id`,`headervalue_id`),
  KEY `physmessage_id` (`physmessage_id`),
  KEY `headername_id` (`headername_id`),
  KEY `headervalue_id` (`headervalue_id`),
  KEY `physmessage_id_headername_id` (`physmessage_id`,`headername_id`),
  KEY `physmessage_id_headervalue_id` (`physmessage_id`,`headervalue_id`),
  KEY `headername_id_headervalue_id` (`headername_id`,`headervalue_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- Change columns
ALTER TABLE `dbmail_acl`
  MODIFY COLUMN `user_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
  MODIFY COLUMN `mailbox_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
  ADD COLUMN deleted_flag TINYINT(1) NOT NULL DEFAULT '0',
  ADD COLUMN expunge_flag TINYINT(1) NOT NULL DEFAULT '0';
UPDATE dbmail_acl SET deleted_flag=delete_flag, expunge_flag=delete_flag;

ALTER TABLE dbmail_aliases 
  MODIFY COLUMN alias_idnr BIGINT( 20 ) UNSIGNED AUTO_INCREMENT NOT NULL,
  MODIFY COLUMN client_idnr BIGINT(20) UNSIGNED DEFAULT 0 NOT NULL,
  MODIFY COLUMN alias varchar(255) NOT NULL default '',
  MODIFY COLUMN deliver_to varchar(255) NOT NULL default '';

ALTER TABLE `dbmail_auto_notifications`
  MODIFY COLUMN `user_idnr` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0';

ALTER TABLE `dbmail_auto_replies`
  MODIFY COLUMN `user_idnr` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0';

ALTER TABLE `dbmail_envelope`
  MODIFY COLUMN `physmessage_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
  MODIFY COLUMN id BIGINT(20) UNSIGNED AUTO_INCREMENT NOT NULL;

ALTER TABLE `dbmail_filters`
  MODIFY COLUMN `user_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0';

ALTER TABLE `dbmail_keywords`
  MODIFY COLUMN `message_idnr` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0';

ALTER TABLE `dbmail_mailboxes`
  MODIFY COLUMN `owner_idnr` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
  MODIFY COLUMN mailbox_idnr BIGINT(20) UNSIGNED AUTO_INCREMENT NOT NULL,
  MODIFY COLUMN name VARCHAR(255) NOT NULL DEFAULT '',
  ADD seq bigint DEFAULT 0 NOT NULL,
  ADD KEY seq (seq);

ALTER TABLE `dbmail_messages`
  MODIFY COLUMN message_idnr BIGINT(20) UNSIGNED AUTO_INCREMENT NOT NULL,
  MODIFY COLUMN `physmessage_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
  MODIFY COLUMN `mailbox_idnr` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0';

ALTER TABLE dbmail_pbsp 
  MODIFY COLUMN idnr BIGINT(20) UNSIGNED AUTO_INCREMENT NOT NULL;

ALTER TABLE dbmail_physmessage 
  MODIFY COLUMN id BIGINT(20) UNSIGNED AUTO_INCREMENT NOT NULL,
  MODIFY COLUMN messagesize BIGINT(20) UNSIGNED DEFAULT 0 NOT NULL,
  MODIFY COLUMN rfcsize BIGINT(20) UNSIGNED DEFAULT 0 NOT NULL;

ALTER TABLE `dbmail_referencesfield`
  MODIFY COLUMN `id` BIGINT( 20 ) UNSIGNED AUTO_INCREMENT NOT NULL,
  MODIFY COLUMN `physmessage_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0';

ALTER TABLE `dbmail_sievescripts`
  MODIFY COLUMN `owner_idnr` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
  MODIFY COLUMN name varchar(255) NOT NULL,
  ADD UNIQUE INDEX dbmail_sievescripts_1 (owner_idnr, name);

ALTER TABLE `dbmail_subscription`
  MODIFY COLUMN `user_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
  MODIFY COLUMN `mailbox_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0';

ALTER TABLE dbmail_users 
  MODIFY COLUMN user_idnr BIGINT(20) UNSIGNED AUTO_INCREMENT NOT NULL,
  MODIFY COLUMN client_idnr BIGINT(20) UNSIGNED DEFAULT 0 NOT NULL,
  MODIFY COLUMN maxmail_size BIGINT(20) DEFAULT 0 NOT NULL,
  MODIFY COLUMN curmail_size BIGINT(20) DEFAULT 0 NOT NULL,
  MODIFY COLUMN maxsieve_size BIGINT(20) DEFAULT 0 NOT NULL,
  MODIFY COLUMN cursieve_size BIGINT(20) DEFAULT 0 NOT NULL,
  MODIFY COLUMN userid varchar(255) NOT NULL default '',
  MODIFY COLUMN passwd varchar(255) NOT NULL default '',
  MODIFY COLUMN encryption_type varchar(255) NOT NULL default '';

ALTER TABLE dbmail_replycache 
  MODIFY COLUMN to_addr varchar(255) NOT NULL default '',
  MODIFY COLUMN from_addr varchar(255) NOT NULL default '',
  MODIFY COLUMN handle varchar(255) NOT NULL default '';

ALTER TABLE dbmail_usermap 
  MODIFY COLUMN login varchar(255) NOT NULL,
  MODIFY COLUMN sock_allow varchar(255) NOT NULL,
  MODIFY COLUMN sock_deny varchar(255) NOT NULL,
  MODIFY COLUMN userid varchar(255) NOT NULL;
  
-- Create Foreign Keys and change columns
ALTER TABLE `dbmail_acl`
  ADD CONSTRAINT `dbmail_acl_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `dbmail_users` (`user_idnr`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `dbmail_acl_ibfk_2` FOREIGN KEY (`mailbox_id`) REFERENCES `dbmail_mailboxes` (`mailbox_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_auto_notifications`
  ADD CONSTRAINT `dbmail_auto_notifications_ibfk_1` FOREIGN KEY (`user_idnr`) REFERENCES `dbmail_users` (`user_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_auto_replies`
  ADD CONSTRAINT `dbmail_auto_replies_ibfk_1` FOREIGN KEY (`user_idnr`) REFERENCES `dbmail_users` (`user_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_envelope`
  ADD UNIQUE KEY physmessage_id_2 (physmessage_id),
  ADD CONSTRAINT `dbmail_envelope_ibfk_1` FOREIGN KEY (`physmessage_id`) REFERENCES `dbmail_physmessage` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_filters`
  ADD CONSTRAINT `dbmail_filters_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `dbmail_users` (`user_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_header`
  ADD CONSTRAINT `dbmail_header_ibfk_1` FOREIGN KEY (`physmessage_id`) REFERENCES `dbmail_physmessage` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `dbmail_header_ibfk_2` FOREIGN KEY (`headername_id`) REFERENCES `dbmail_headername` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `dbmail_header_ibfk_3` FOREIGN KEY (`headervalue_id`) REFERENCES `dbmail_headervalue` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_keywords`
  ADD CONSTRAINT `dbmail_keywords_ibfk_1` FOREIGN KEY (`message_idnr`) REFERENCES `dbmail_messages` (`message_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_mailboxes`
  ADD CONSTRAINT `dbmail_mailboxes_ibfk_1` FOREIGN KEY (`owner_idnr`) REFERENCES `dbmail_users` (`user_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_messages`
  ADD CONSTRAINT `dbmail_messages_ibfk_1` FOREIGN KEY (`physmessage_id`) REFERENCES `dbmail_physmessage` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `dbmail_messages_ibfk_2` FOREIGN KEY (`mailbox_idnr`) REFERENCES `dbmail_mailboxes` (`mailbox_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_partlists`
  ADD CONSTRAINT `dbmail_partlists_ibfk_1` FOREIGN KEY (`physmessage_id`) REFERENCES `dbmail_physmessage` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `dbmail_partlists_ibfk_2` FOREIGN KEY (`part_id`) REFERENCES `dbmail_mimeparts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_referencesfield`
  ADD CONSTRAINT `dbmail_referencesfield_ibfk_1` FOREIGN KEY (`physmessage_id`) REFERENCES `dbmail_physmessage` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_sievescripts`
  ADD CONSTRAINT `dbmail_sievescripts_ibfk_1` FOREIGN KEY (`owner_idnr`) REFERENCES `dbmail_users` (`user_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `dbmail_subscription`
  ADD CONSTRAINT `dbmail_subscription_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `dbmail_users` (`user_idnr`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `dbmail_subscription_ibfk_2` FOREIGN KEY (`mailbox_id`) REFERENCES `dbmail_mailboxes` (`mailbox_idnr`) ON DELETE CASCADE ON UPDATE CASCADE;

-- views for IMAP sort

DROP VIEW IF EXISTS dbmail_fromfield;
CREATE VIEW dbmail_fromfield AS
        SELECT physmessage_id,sortfield AS fromfield
        FROM dbmail_messages m
        JOIN dbmail_header h USING (physmessage_id)
        JOIN dbmail_headername n ON h.headername_id = n.id
        JOIN dbmail_headervalue v ON h.headervalue_id = v.id
WHERE n.headername='from';

DROP VIEW IF EXISTS dbmail_ccfield;
CREATE VIEW dbmail_ccfield AS
        SELECT physmessage_id,sortfield AS ccfield
        FROM dbmail_messages m
        JOIN dbmail_header h USING (physmessage_id)
        JOIN dbmail_headername n ON h.headername_id = n.id
        JOIN dbmail_headervalue v ON h.headervalue_id = v.id
WHERE n.headername='cc';

DROP VIEW IF EXISTS dbmail_tofield;
CREATE VIEW dbmail_tofield AS
        SELECT physmessage_id,sortfield AS tofield
        FROM dbmail_messages m
        JOIN dbmail_header h USING (physmessage_id)
        JOIN dbmail_headername n ON h.headername_id = n.id
        JOIN dbmail_headervalue v ON h.headervalue_id = v.id
WHERE n.headername='to';

DROP VIEW IF EXISTS dbmail_subjectfield;
CREATE VIEW dbmail_subjectfield AS
        SELECT physmessage_id,headervalue AS subjectfield
        FROM dbmail_messages m
        JOIN dbmail_header h USING (physmessage_id)
        JOIN dbmail_headername n ON h.headername_id = n.id
        JOIN dbmail_headervalue v ON h.headervalue_id = v.id
WHERE n.headername='subject';

DROP VIEW IF EXISTS dbmail_datefield;
CREATE VIEW dbmail_datefield AS
        SELECT physmessage_id,datefield,sortfield
        FROM dbmail_messages m
        JOIN dbmail_header h USING (physmessage_id)
        JOIN dbmail_headername n ON h.headername_id = n.id
        JOIN dbmail_headervalue v ON h.headervalue_id = v.id
WHERE n.headername='date';

SET FOREIGN_KEY_CHECKS=1;

