<?xml version="1.0" encoding="UTF-8"?>

<!-- Differential patch for M/Monit database schema version 16 to 17 -->

<patch>

<!-- sqlite -->

<statements type="sqlite">

<comment>Check database integrity before upgrade</comment>
<statement>
PRAGMA integrity_check;
</statement>
<statement>
PRAGMA foreign_key_check;
</statement>

<comment>Disable foreign keys</comment>
<statement>
PRAGMA foreign_keys=OFF;
</statement>

<comment>Add default 5 minutes programtimeout to mmonit table</comment>
<statement>
ALTER TABLE mmonit ADD COLUMN programtimeout INTEGER;
</statement>
<statement>
UPDATE mmonit SET programtimeout=300;
</statement>

<comment>Convert users to integer key</comment>
<statement>
CREATE TABLE users_backup (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  uname VARCHAR(20) UNIQUE NOT NULL,
  password VARCHAR(56) NOT NULL,
  fullname VARCHAR(255),
  title VARCHAR(255),
  email VARCHAR(255),
  phone VARCHAR(40),
  mobile VARCHAR(40),
  imname VARCHAR(255),
  imtype VARCHAR(20),
  image VARCHAR(255),
  refresh INTEGER DEFAULT 5000
);
</statement>
<statement>
INSERT INTO users_backup (uname, password, fullname, title, email, phone, mobile, imname, imtype, image, refresh) SELECT uname, password, fullname, title, email, phone, mobile, imname, imtype, image, refresh FROM users;
</statement>
<statement>
DROP TABLE users;
</statement>
<statement>
CREATE TABLE users (
  id INTEGER PRIMARY KEY,
  uname VARCHAR(20) UNIQUE NOT NULL,
  password VARCHAR(56) NOT NULL,
  fullname VARCHAR(255),
  title VARCHAR(255),
  email VARCHAR(255),
  phone VARCHAR(40),
  mobile VARCHAR(40),
  imname VARCHAR(255),
  imtype VARCHAR(20),
  image VARCHAR(255),
  refresh INTEGER DEFAULT 5000
);
</statement>
<statement>
INSERT INTO users SELECT * FROM users_backup;
</statement>
<statement>
DROP TABLE users_backup;
</statement>
<statement>
CREATE INDEX users_uname_index ON users(uname);
</statement>

<comment>Convert roles to integer key and add ACL support</comment>
<statement>
CREATE TABLE roles_backup (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  role VARCHAR(100) UNIQUE NOT NULL,
  description VARCHAR(255),
  admin CHAR(1),
  active CHAR(1),
  builtin CHAR(1)
);
</statement>
<statement>
INSERT INTO roles_backup (role, description, admin, active, builtin) SELECT role, description, 0, 1, 0 FROM roles;
</statement>
<statement>
DROP TABLE roles;
</statement>
<statement>
CREATE TABLE roles (
  id INTEGER PRIMARY KEY,
  role VARCHAR(100) UNIQUE NOT NULL,
  description VARCHAR(255),
  admin CHAR(1),
  active CHAR(1),
  builtin CHAR(1)
);
</statement>
<statement>
INSERT INTO roles SELECT * FROM roles_backup;
</statement>
<statement>
DROP TABLE roles_backup;
</statement>
<statement>
CREATE INDEX roles_role_index ON roles(role);
</statement>

<comment>Convert userroles to integer keys</comment>
<statement>
CREATE TEMPORARY TABLE eventnotice_backup (
  eventid INTEGER NOT NULL,
  date INTEGER NOT NULL,
  uname VARCHAR(20) NOT NULL,
  notice TEXT NOT NULL
);
</statement>
<statement>
INSERT INTO eventnotice_backup(eventid, date, uname, notice) SELECT eventid, date, uname, notice FROM eventnotice;
</statement>
<statement>
DROP TABLE eventnotice;
</statement>
<statement>
CREATE TABLE eventnotice (
  eventid INTEGER NOT NULL,
  date INTEGER NOT NULL,
  uname VARCHAR(20) NOT NULL,
  notice TEXT NOT NULL,
  CONSTRAINT eventnotice_eventid_fk FOREIGN KEY(eventid) REFERENCES event(id) ON DELETE CASCADE
);
</statement>
<statement>
INSERT INTO eventnotice SELECT * FROM eventnotice_backup;
</statement>
<statement>
DROP TABLE eventnotice_backup;
</statement>

<statement>
CREATE TEMPORARY TABLE userroles_backup (
  userid INTEGER,
  roleid INTEGER
);
</statement>
<statement>
INSERT INTO userroles_backup (userid, roleid) SELECT (SELECT id FROM users u WHERE u.uname=userroles.uname), (SELECT id FROM roles r WHERE r.role=userroles.role) FROM userroles;
</statement>
<statement>
DROP TABLE userroles;
</statement>
<statement>
CREATE TABLE userroles (
  userid INTEGER NOT NULL,
  roleid INTEGER NOT NULL,
  PRIMARY KEY(userid, roleid),
  CONSTRAINT userroles_userid_fk FOREIGN KEY(userid) REFERENCES users(id) ON DELETE CASCADE,
  CONSTRAINT userroles_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) ON DELETE CASCADE
);
</statement>
<statement>
INSERT INTO userroles SELECT * FROM userroles_backup;
</statement>
<statement>
CREATE INDEX userroles_roleid_index ON userroles(roleid);
</statement>
<statement>
DROP TABLE userroles_backup;
</statement>

<comment>Convert eventfilter to integer keys</comment>
<statement>
CREATE TABLE eventfilter_backup (
  eventid INTEGER,
  userid INTEGER NOT NULL,
  CONSTRAINT eventfilter_eventid_fk FOREIGN KEY(eventid) REFERENCES event(id) ON DELETE CASCADE,
  CONSTRAINT eventfilter_userid_fk FOREIGN KEY(userid) REFERENCES users(id) ON DELETE CASCADE
);
</statement>
<statement>
INSERT INTO eventfilter_backup (eventid, userid) SELECT eventid, (SELECT id FROM users u WHERE u.uname=eventfilter.uname) FROM eventfilter;
</statement>
<statement>
DROP TABLE eventfilter;
</statement>
<statement>
CREATE TABLE eventfilter (
  eventid INTEGER NOT NULL,
  userid INTEGER NOT NULL,
  CONSTRAINT eventfilter_eventid_fk FOREIGN KEY(eventid) REFERENCES event(id) ON DELETE CASCADE,
  CONSTRAINT eventfilter_userid_fk FOREIGN KEY(userid) REFERENCES users(id) ON DELETE CASCADE
);
</statement>
<statement>
INSERT INTO eventfilter SELECT * FROM eventfilter_backup;
</statement>
<statement>
DROP TABLE eventfilter_backup;
</statement>
<statement>
CREATE INDEX eventfilter_eventid_index ON eventfilter(eventid);
</statement>
<statement>
CREATE INDEX eventfilter_userid_index ON eventfilter(userid);
</statement>

<comment>Convert uname based alert rules to user id</comment>
<statement>
UPDATE actionrowtarget SET target=(SELECT id FROM users WHERE users.uname=target) WHERE actionrowid IN (SELECT id FROM actionrow WHERE action IN (0,2));
</statement>

<comment>Add ACL tables</comment>
<statement>
CREATE TABLE rolerow (
  id INTEGER PRIMARY KEY,
  roleid INTEGER NOT NULL,
  CONSTRAINT rolerow_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerow_roleid_index ON rolerow(roleid);
</statement>
<statement>
CREATE TABLE rolerowhost (
  rolerowid INTEGER,
  hostid INTEGER,
  CONSTRAINT rolerowhost_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) ON DELETE CASCADE,
  CONSTRAINT rolerowhost_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerowhost_rolerowid_index ON rolerowhost(rolerowid);
</statement>
<statement>
CREATE INDEX rolerowhost_hostid_index ON rolerowhost(hostid);
</statement>
<statement>
CREATE TABLE rolerowhostgroup (
  rolerowid INTEGER,
  hostgroupid INTEGER,
  CONSTRAINT rolerowhostgroup_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) ON DELETE CASCADE,
  CONSTRAINT rolerowhostgroup_hostgroupid_fk FOREIGN KEY(hostgroupid) REFERENCES hostgroup(id) ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerowhostgroup_rolerowid_index ON rolerowhostgroup(rolerowid);
</statement>
<statement>
CREATE INDEX rolerowhostgroup_hostgroupid_index ON rolerowhostgroup(hostgroupid);
</statement>
<statement>
CREATE TABLE rolerowpermission (
  rolerowid INTEGER,
  permission INTEGER,
  CONSTRAINT rolerowstate_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerowpermission_roleid_index ON rolerowpermission(rolerowid);
</statement>

<comment>Add hostid to statistics_events table (the table is initialized on each M/Monit start => no need to migrate data)</comment>
<statement>
DROP TABLE statistics_events;
</statement>
<statement>
CREATE TABLE statistics_events  (
  timeframe INTEGER NOT NULL,
  hostid INTEGER NOT NULL,
  state INTEGER NOT NULL,
  count INTEGER NOT NULL,
  CONSTRAINT statistics_events_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX statistics_events_state_index ON statistics_events(state);
</statement>
<statement>
CREATE INDEX statistics_events_hostid_index ON statistics_events(hostid);
</statement>

<comment>Add sendername and senderaddress to messageformat table</comment>
<statement>
CREATE TEMPORARY TABLE messageformat_backup (
  id INTEGER PRIMARY KEY,
  description VARCHAR(255),
  sendername VARCHAR(255),
  senderaddress VARCHAR(255),
  subjectsingle VARCHAR(255),
  subjectmulti VARCHAR(255),
  txtheader TEXT,
  txtbody TEXT,
  txtfooter TEXT,
  htmlheader TEXT,
  htmlbody TEXT,
  htmlfooter TEXT,
  contenttype INTEGER,
  isdefault CHAR(1)
);
</statement>
<statement>
INSERT INTO messageformat_backup (id, description, sendername, senderaddress, subjectsingle, subjectmulti, txtheader, txtbody, txtfooter, htmlheader, htmlbody, htmlfooter, contenttype, isdefault) SELECT id, description, "M/Monit", sender, subjectsingle, subjectmulti, txtheader, txtbody, txtfooter, htmlheader, htmlbody, htmlfooter, contenttype, isdefault FROM messageformat;
</statement>
<statement>
DROP TABLE messageformat;
</statement>
<statement>
CREATE TABLE messageformat (
  id INTEGER PRIMARY KEY,
  description VARCHAR(255),
  sendername VARCHAR(255),
  senderaddress VARCHAR(255),
  subjectsingle VARCHAR(255),
  subjectmulti VARCHAR(255),
  txtheader TEXT,
  txtbody TEXT,
  txtfooter TEXT,
  htmlheader TEXT,
  htmlbody TEXT,
  htmlfooter TEXT,
  contenttype INTEGER,
  isdefault CHAR(1)
);
</statement>
<statement>
INSERT INTO messageformat SELECT * FROM messageformat_backup;
</statement>
<statement>
DROP TABLE messageformat_backup;
</statement>

<comment>Add sendername and senderaddress to message table</comment>
<statement>
CREATE TEMPORARY TABLE message_backup (
  id INTEGER PRIMARY KEY,
  type INTEGER,
  contenttype VARCHAR(255),
  sendername VARCHAR(255),
  senderaddress VARCHAR(255),
  subject VARCHAR(255),
  body TEXT,
  created INTEGER,
  retry INTEGER
);
</statement>
<statement>
INSERT INTO message_backup (id, type, contenttype, sendername, senderaddress, subject, body, created, retry) SELECT id, type, contenttype, "M/Monit", sender, subject, body, created, retry FROM message;
</statement>
<statement>
DROP TABLE message;
</statement>
<statement>
CREATE TABLE message (
  id INTEGER PRIMARY KEY,
  type INTEGER,
  contenttype VARCHAR(255),
  sendername VARCHAR(255),
  senderaddress VARCHAR(255),
  subject VARCHAR(255),
  body TEXT,
  created INTEGER,
  retry INTEGER
);
</statement>
<statement>
INSERT INTO message SELECT * FROM message_backup;
</statement>
<statement>
DROP TABLE message_backup;
</statement>

<comment>Add timeout to actionrow table</comment>
<statement>
ALTER TABLE actionrow ADD COLUMN timeout INTEGER DEFAULT -1;
</statement>

<comment>Create temporary table for generating integer id</comment>
<statement>
CREATE TEMPORARY TABLE tmpseq (
     id INTEGER PRIMARY KEY AUTOINCREMENT,
     value VARCHAR(20) NOT NULL
);
</statement>

<comment>Update admin role</comment>
<statement>
UPDATE roles SET description='The Administrator role' WHERE role='admin';
</statement>
<statement>
UPDATE roles SET admin=1, active=1, builtin=1 WHERE role='admin';
</statement>
<comment>Assign collector, view and service actions permissions to admin role</comment>
<statement>
INSERT INTO tmpseq (value) VALUES ("adminrow");
</statement>
<statement>
INSERT INTO rolerow (id, roleid) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), (SELECT id FROM roles WHERE role='admin'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), 1);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), 2);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), 4);
</statement>

<comment>Update monit role and rename it to GUI</comment>
<statement>
UPDATE roles SET role='GUI' WHERE role='monit';
</statement>
<statement>
UPDATE roles SET description='The user role for GUI access' WHERE role='GUI';
</statement>
<statement>
UPDATE roles SET admin=0, active=1, builtin=0 WHERE role='GUI';
</statement>
<comment>Assign view and service actions permissions to GUI role</comment>
<statement>
INSERT INTO tmpseq (value) VALUES ("guirow");
</statement>
<statement>
INSERT INTO rolerow (id, roleid) VALUES ((SELECT id FROM tmpseq WHERE value="guirow"), (SELECT id FROM roles WHERE role='GUI'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="guirow"), 2);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="guirow"), 4);
</statement>

<comment>Add a new collector role (no access to the GUI)</comment>
<statement>
INSERT INTO tmpseq (value) VALUES ("collector");
</statement>
<statement>
INSERT INTO roles (id, role, description, admin, active, builtin) VALUES ((SELECT id FROM tmpseq WHERE value="collector"), 'collector', 'Collector', 0, 1, 1);
</statement>
<statement>
INSERT INTO tmpseq (value) VALUES ("collectorrow");
</statement>
<statement>
INSERT INTO rolerow (id, roleid) VALUES ((SELECT id FROM tmpseq WHERE value="collectorrow"), (SELECT id FROM roles WHERE role='collector'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="collectorrow"), 1);
</statement>

<comment>Add all non-admin users to GUI and collector roles for backward compatibility</comment>
<statement>
DELETE FROM userroles WHERE roleid != (SELECT id FROM roles WHERE role='admin');
</statement>
<statement>
INSERT INTO userroles (userid, roleid) SELECT users.id, roles.id  FROM users, roles WHERE role='GUI';
</statement>
<statement>
INSERT INTO userroles (userid, roleid) SELECT users.id, roles.id  FROM users, roles WHERE role='collector';
</statement>

<comment>Add platformuptime to host table</comment>
<statement>
ALTER TABLE host ADD COLUMN platformuptime INTEGER DEFAULT -1;
</statement>

<comment>Check database integrity after upgrade</comment>
<statement>
PRAGMA integrity_check;
</statement>
<statement>
PRAGMA foreign_key_check;
</statement>

<comment>Enable foreign keys</comment>
<statement>
PRAGMA foreign_keys=ON;
</statement>

<comment>Cleanup</comment>
<statement>
DROP TABLE tmpseq;
</statement>

</statements>


<!-- mysql -->

<statements type="mysql">

<comment>Add default 5 minutes programtimeout to mmonit table</comment>
<statement>
ALTER TABLE mmonit ADD COLUMN programtimeout INTEGER AFTER skew;
</statement>
<statement>
UPDATE mmonit SET programtimeout=300;
</statement>

<comment>Create temporary table for generating integer id</comment>
<statement>
CREATE TEMPORARY TABLE tmpseq (
     id INTEGER AUTO_INCREMENT PRIMARY KEY,
     value VARCHAR(20) NOT NULL
);
</statement>

<comment>Convert users to integer key</comment>
<statement>
ALTER TABLE userroles DROP FOREIGN KEY userroles_role_fk;
</statement>
<statement>
ALTER TABLE userroles DROP FOREIGN KEY userroles_uname_fk;
</statement>
<statement>
ALTER TABLE eventfilter DROP FOREIGN KEY eventfilter_uname_fk;
</statement>
<statement>
ALTER TABLE eventnotice DROP FOREIGN KEY eventnotice_uname_fk;
</statement>
<statement>
ALTER TABLE eventnotice DROP KEY eventnotice_uname_fk;
</statement>
<statement>
ALTER TABLE users DROP PRIMARY KEY;
</statement>
<statement>
ALTER TABLE users MODIFY COLUMN uname VARCHAR(20) UNIQUE NOT NULL;
</statement>
<statement>
ALTER TABLE users ADD COLUMN id INTEGER FIRST;
</statement>
<statement>
INSERT INTO tmpseq (value) SELECT uname FROM users;
</statement>
<statement>
UPDATE users SET id=(SELECT id FROM tmpseq WHERE value=uname);
</statement>
<statement>
DELETE FROM tmpseq;
</statement>
<statement>
ALTER TABLE users ADD PRIMARY KEY (id);
</statement>
<statement>
CREATE INDEX users_uname_index ON users(uname);
</statement>

<comment>Convert roles to integer key and add ACL support</comment>
<statement>
ALTER TABLE roles DROP PRIMARY KEY;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN id INTEGER FIRST;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN admin BOOLEAN DEFAULT 0 AFTER description;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN active BOOLEAN DEFAULT 0 AFTER admin;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN builtin BOOLEAN DEFAULT 0 AFTER active;
</statement>
<statement>
INSERT INTO tmpseq (value) SELECT role FROM roles;
</statement>
<statement>
UPDATE roles SET id=(SELECT id FROM tmpseq WHERE value=role);
</statement>
<statement>
ALTER TABLE roles ADD PRIMARY KEY (id);
</statement>
<statement>
CREATE INDEX roles_role_index ON roles(role);
</statement>
<statement>
DELETE FROM tmpseq;
</statement>

<comment>Rise allowed role name size to 100 characters</comment>
<statement>
ALTER TABLE roles MODIFY COLUMN role VARCHAR(100) UNIQUE NOT NULL;
</statement>

<comment>Convert userroles to integer keys</comment>
<statement>
ALTER TABLE userroles DROP PRIMARY KEY;
</statement>
<statement>
ALTER TABLE userroles ADD COLUMN userid INTEGER NOT NULL AFTER role;
</statement>
<statement>
ALTER TABLE userroles ADD COLUMN roleid INTEGER NOT NULL AFTER userid;
</statement>
<statement>
UPDATE userroles SET userid=(SELECT id FROM users u WHERE u.uname=userroles.uname), roleid=(SELECT id FROM roles r WHERE r.role=userroles.role);
</statement>
<statement>
ALTER TABLE userroles ADD PRIMARY KEY (userid, roleid);
</statement>
<statement>
ALTER TABLE userroles ADD CONSTRAINT userroles_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) ON DELETE CASCADE;
</statement>
<statement>
ALTER TABLE userroles ADD CONSTRAINT userroles_userid_fk FOREIGN KEY(userid) REFERENCES users(id) ON DELETE CASCADE;
</statement>
<statement>
CREATE INDEX userroles_roleid_index ON userroles(roleid);
</statement>
<statement>
ALTER TABLE userroles DROP COLUMN role;
</statement>
<statement>
ALTER TABLE userroles DROP COLUMN uname;
</statement>

<comment>Convert eventfilter to integer keys</comment>
<statement>
ALTER TABLE eventfilter ADD COLUMN userid INTEGER NOT NULL;
</statement>
<statement>
UPDATE eventfilter SET userid=(SELECT u.id FROM users u WHERE u.uname=eventfilter.uname);
</statement>
<statement>
ALTER TABLE eventfilter ADD CONSTRAINT eventfilter_userid_fk FOREIGN KEY (userid) REFERENCES users (id) ON DELETE CASCADE;
</statement>
<statement>
ALTER TABLE eventfilter MODIFY COLUMN eventid INTEGER NOT NULL;
</statement>
<statement>
ALTER TABLE eventfilter DROP COLUMN uname;
</statement>
<statement>
CREATE INDEX eventfilter_userid_index ON eventfilter(userid);
</statement>

<comment>Convert uname based alert rules to user id</comment>
<statement>
UPDATE actionrowtarget SET target=(SELECT id FROM users WHERE users.uname=target) WHERE actionrowid IN (SELECT id FROM actionrow WHERE action IN (0,2));
</statement>

<comment>Add ACL tables</comment>
<statement>
CREATE TABLE rolerow (
  id INTEGER PRIMARY KEY,
  roleid INTEGER NOT NULL,
  INDEX rolerow_roleid_index (roleid),
  CONSTRAINT rolerow_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</statement>
<statement>
CREATE TABLE rolerowhost (
  rolerowid INTEGER,
  hostid INTEGER,
  INDEX rolerowhost_rolerowid_index (rolerowid),
  INDEX rolerowhost_hostid_index (hostid),
  CONSTRAINT rolerowhost_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) ON DELETE CASCADE,
  CONSTRAINT rolerowhost_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</statement>
<statement>
CREATE TABLE rolerowhostgroup (
  rolerowid INTEGER,
  hostgroupid INTEGER,
  INDEX rolerowhostgroup_rolerowid_index (rolerowid),
  INDEX rolerowhostgroup_hostgroupid_index (hostgroupid),
  CONSTRAINT rolerowhostgroup_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) ON DELETE CASCADE,
  CONSTRAINT rolerowhostgroup_hostgroupid_fk FOREIGN KEY(hostgroupid) REFERENCES hostgroup(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</statement>
<statement>
CREATE TABLE rolerowpermission (
  rolerowid INTEGER,
  permission INTEGER,
  INDEX rolerowpermission_roleid_index (rolerowid),
  CONSTRAINT rolerowstate_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</statement>

<comment>Add hostid to statistics_events table (the table is initialized on each M/Monit start => no need to migrate data)</comment>
<statement>
DELETE FROM statistics_events;
</statement>
<statement>
ALTER TABLE statistics_events ADD COLUMN hostid INTEGER NOT NULL AFTER timeframe;
</statement>
<statement>
ALTER TABLE statistics_events ADD CONSTRAINT statistics_events_hostid_fk FOREIGN KEY (hostid) REFERENCES host (id) ON DELETE CASCADE;
</statement>
<statement>
CREATE INDEX statistics_events_hostid_index ON statistics_events(hostid);
</statement>

<comment>Add sendername and senderaddress to messageformat table</comment>
<statement>
ALTER TABLE messageformat CHANGE sender senderaddress VARCHAR(255);
</statement>
<statement>
ALTER TABLE messageformat ADD COLUMN sendername VARCHAR(255) AFTER description;
</statement>
<statement>
UPDATE messageformat SET sendername='M/Monit';
</statement>

<comment>Add sendername and senderaddress to message table</comment>
<statement>
ALTER TABLE message CHANGE sender senderaddress VARCHAR(255);
</statement>
<statement>
ALTER TABLE message ADD COLUMN sendername VARCHAR(255) AFTER contenttype;
</statement>
<statement>
UPDATE message SET sendername='M/Monit';
</statement>

<comment>Add timeout to actionrow table</comment>
<statement>
ALTER TABLE actionrow ADD COLUMN timeout INTEGER DEFAULT -1 AFTER repetition;
</statement>

<comment>Update admin role</comment>
<statement>
UPDATE roles SET description='The Administrator role' WHERE role='admin';
</statement>
<statement>
UPDATE roles SET admin=1, active=1, builtin=1 WHERE role='admin';
</statement>
<comment>Assign collector, view and service actions permissions to admin role</comment>
<statement>
INSERT INTO tmpseq (value) VALUES ("adminrow");
</statement>
<statement>
INSERT INTO rolerow (id, roleid) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), (SELECT id FROM roles WHERE role='admin'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), 1);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), 2);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value="adminrow"), 4);
</statement>

<comment>Update monit role and rename it to GUI</comment>
<statement>
UPDATE roles SET role='GUI' WHERE role='monit';
</statement>
<statement>
UPDATE roles SET description='The user role for GUI access' WHERE role='GUI';
</statement>
<statement>
UPDATE roles SET admin=0, active=1, builtin=0 WHERE role='GUI';
</statement>
<comment>Assign view and service actions permissions to GUI role</comment>
<statement>
INSERT INTO tmpseq (value) VALUES ("guirow");
</statement>
<statement>
INSERT INTO rolerow (id, roleid) VALUES ((SELECT id FROM tmpseq WHERE value="guirow"), (SELECT id FROM roles WHERE role='GUI'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value='guirow'), 2);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value='guirow'), 4);
</statement>

<comment>Add a new collector role (no access to the GUI)</comment>
<statement>
INSERT INTO tmpseq (value) VALUES ("collector");
</statement>
<statement>
INSERT INTO roles (id, role, description, admin, active, builtin) VALUES ((SELECT id FROM tmpseq WHERE value="collector"), "collector", "Collector", 0, 1, 1);
</statement>
<statement>
INSERT INTO tmpseq (value) VALUES ("collectorrow");
</statement>
<statement>
INSERT INTO rolerow (id, roleid) VALUES ((SELECT id FROM tmpseq WHERE value='collectorrow'), (SELECT id FROM roles WHERE role='collector'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES ((SELECT id FROM tmpseq WHERE value='collectorrow'), 1);
</statement>

<comment>Add all non-admin users to GUI and collector roles for backward compatibility</comment>
<statement>
DELETE FROM userroles WHERE roleid != (SELECT id FROM roles WHERE role='admin');
</statement>
<statement>
INSERT INTO userroles (userid, roleid) SELECT users.id, roles.id  FROM users, roles WHERE role='GUI';
</statement>
<statement>
INSERT INTO userroles (userid, roleid) SELECT users.id, roles.id  FROM users, roles WHERE role='collector';
</statement>

<comment>Add platformuptime to host table</comment>
<statement>
ALTER TABLE host ADD COLUMN platformuptime BIGINT DEFAULT -1;
</statement>

<comment>Cleanup</comment>

<statement>
DROP TABLE tmpseq;
</statement>

</statements>


<!-- postgresql -->

<statements type="postgresql">

<comment>Add default 5 minutes programtimeout to mmonit table</comment>
<statement>
ALTER TABLE mmonit ADD COLUMN programtimeout INTEGER;
</statement>
<statement>
UPDATE mmonit SET programtimeout=300;
</statement>

<comment>Create temporary sequence for generating integer id</comment>
<statement>
CREATE TEMPORARY SEQUENCE tmpseq;
</statement>

<comment>Convert users to integer key</comment>
<statement>
ALTER TABLE userroles DROP CONSTRAINT userroles_role_fk;
</statement>
<statement>
ALTER TABLE userroles DROP CONSTRAINT userroles_uname_fk;
</statement>
<statement>
ALTER TABLE eventfilter DROP CONSTRAINT eventfilter_uname_fkey;
</statement>
<statement>
ALTER TABLE eventnotice DROP CONSTRAINT eventnotice_uname_fk;
</statement>
<statement>
ALTER TABLE users DROP CONSTRAINT users_pkey;
</statement>
<statement>
ALTER TABLE users ADD CONSTRAINT users_uname_unique UNIQUE (uname);
</statement>
<statement>
ALTER TABLE users ALTER COLUMN uname SET NOT NULL;
</statement>
<statement>
ALTER TABLE users ADD COLUMN id INTEGER;
</statement>
<statement>
UPDATE users SET id=NEXTVAL('tmpseq');
</statement>
<statement>
ALTER TABLE users ADD PRIMARY KEY (id);
</statement>
<statement>
CREATE INDEX users_uname_index ON users(uname);
</statement>

<comment>Convert roles to integer key and add ACL support</comment>
<statement>
ALTER TABLE roles DROP CONSTRAINT roles_pkey;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN id INTEGER;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN admin SMALLINT DEFAULT 0;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN active SMALLINT DEFAULT 0;
</statement>
<statement>
ALTER TABLE roles ADD COLUMN builtin SMALLINT DEFAULT 0;
</statement>
<statement>
UPDATE roles SET id=NEXTVAL('tmpseq');
</statement>
<statement>
ALTER TABLE roles ADD PRIMARY KEY (id);
</statement>
<statement>
CREATE INDEX roles_role_index ON roles(role);
</statement>
<statement>
ALTER TABLE roles ALTER COLUMN role SET NOT NULL;
</statement>
<statement>
ALTER TABLE roles ADD CONSTRAINT roles_role_unique UNIQUE (role);
</statement>

<comment>Rise allowed role name size to 100 characters</comment>
<statement>
ALTER TABLE roles ALTER COLUMN role SET DATA TYPE CHARACTER VARYING(100);
</statement>

<comment>Convert userroles to integer keys</comment>
<statement>
ALTER TABLE userroles DROP CONSTRAINT userroles_pkey;
</statement>
<statement>
ALTER TABLE userroles ADD COLUMN userid INTEGER;
</statement>
<statement>
ALTER TABLE userroles ADD COLUMN roleid INTEGER;
</statement>
<statement>
UPDATE userroles SET userid=(SELECT id FROM users u WHERE u.uname=userroles.uname), roleid=(SELECT id FROM roles r WHERE r.role=userroles.role);
</statement>
<statement>
ALTER TABLE userroles ALTER COLUMN userid SET NOT NULL;
</statement>
<statement>
ALTER TABLE userroles ALTER COLUMN roleid SET NOT NULL;
</statement>
<statement>
ALTER TABLE userroles ADD PRIMARY KEY (userid, roleid);
</statement>
<statement>
ALTER TABLE userroles ADD CONSTRAINT userroles_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) MATCH FULL ON DELETE CASCADE;
</statement>
<statement>
ALTER TABLE userroles ADD CONSTRAINT userroles_userid_fk FOREIGN KEY(userid) REFERENCES users(id) MATCH FULL ON DELETE CASCADE;
</statement>
<statement>
CREATE INDEX userroles_roleid_index ON userroles(roleid);
</statement>
<statement>
ALTER TABLE userroles DROP COLUMN role;
</statement>
<statement>
ALTER TABLE userroles DROP COLUMN uname;
</statement>

<comment>Convert eventfilter to integer keys</comment>
<statement>
ALTER TABLE eventfilter ADD COLUMN userid INTEGER;
</statement>
<statement>
UPDATE eventfilter SET userid=(SELECT u.id FROM users u WHERE u.uname=eventfilter.uname);
</statement>
<statement>
ALTER TABLE eventfilter ADD CONSTRAINT eventfilter_userid_fk FOREIGN KEY (userid) REFERENCES users (id) MATCH FULL ON DELETE CASCADE;
</statement>
<statement>
ALTER TABLE eventfilter ALTER COLUMN userid SET NOT NULL;
</statement>
<statement>
ALTER TABLE eventfilter ALTER COLUMN eventid SET NOT NULL;
</statement>
<statement>
ALTER TABLE eventfilter DROP COLUMN uname;
</statement>
<statement>
CREATE INDEX eventfilter_userid_index ON eventfilter(userid);
</statement>

<comment>Convert uname based alert rules to user id</comment>
<statement>
UPDATE actionrowtarget SET target=(SELECT id FROM users WHERE users.uname=target) WHERE actionrowid IN (SELECT id FROM actionrow WHERE action IN (0,2));
</statement>

<comment>Add ACL tables</comment>
<statement>
CREATE TABLE rolerow (
  id INTEGER PRIMARY KEY,
  roleid INTEGER NOT NULL,
  CONSTRAINT rolerow_roleid_fk FOREIGN KEY(roleid) REFERENCES roles(id) MATCH FULL ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerow_roleid_index ON rolerow(roleid);
</statement>
<statement>
CREATE TABLE rolerowhost (
  rolerowid INTEGER,
  hostid INTEGER,
  CONSTRAINT rolerowhost_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rolerowhost_hostid_fk FOREIGN KEY(hostid) REFERENCES host(id) MATCH FULL ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerowhost_rolerowid_index ON rolerowhost(rolerowid);
</statement>
<statement>
CREATE INDEX rolerowhost_hostid_index ON rolerowhost(hostid);
</statement>
<statement>
CREATE TABLE rolerowhostgroup (
  rolerowid INTEGER,
  hostgroupid INTEGER,
  CONSTRAINT rolerowhostgroup_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) MATCH FULL ON DELETE CASCADE,
  CONSTRAINT rolerowhostgroup_hostgroupid_fk FOREIGN KEY(hostgroupid) REFERENCES hostgroup(id) MATCH FULL ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerowhostgroup_rolerowid_index ON rolerowhostgroup(rolerowid);
</statement>
<statement>
CREATE INDEX rolerowhostgroup_hostgroupid_index ON rolerowhostgroup(hostgroupid);
</statement>
<statement>
CREATE TABLE rolerowpermission (
  rolerowid INTEGER,
  permission INTEGER,
  CONSTRAINT rolerowstate_rolerowid_fk FOREIGN KEY(rolerowid) REFERENCES rolerow(id) MATCH FULL ON DELETE CASCADE
);
</statement>
<statement>
CREATE INDEX rolerowpermission_roleid_index ON rolerowpermission(rolerowid);
</statement>

<comment>Add hostid to statistics_events table (the table is initialized on each M/Monit start => no need to migrate data)</comment>
<statement>
DELETE FROM statistics_events;
</statement>
<statement>
ALTER TABLE statistics_events ADD COLUMN hostid INTEGER NOT NULL;
</statement>
<statement>
ALTER TABLE statistics_events ADD CONSTRAINT statistics_events_hostid_fk FOREIGN KEY (hostid) REFERENCES host (id) MATCH FULL ON DELETE CASCADE;
</statement>
<statement>
CREATE INDEX statistics_events_hostid_index ON statistics_events(hostid);
</statement>

<comment>Add sendername and senderaddress to messageformat table</comment>
<statement>
ALTER TABLE messageformat RENAME COLUMN sender TO senderaddress;
</statement>
<statement>
ALTER TABLE messageformat ADD COLUMN sendername CHARACTER VARYING(255);
</statement>
<statement>
UPDATE messageformat SET sendername='M/Monit';
</statement>

<comment>Add sendername and senderaddress to message table</comment>
<statement>
ALTER TABLE message RENAME COLUMN sender TO senderaddress;
</statement>
<statement>
ALTER TABLE message ADD COLUMN sendername CHARACTER VARYING(255);
</statement>
<statement>
UPDATE message SET sendername='M/Monit';
</statement>

<comment>Add timeout to actionrow table</comment>
<statement>
ALTER TABLE actionrow ADD COLUMN timeout INTEGER DEFAULT -1;
</statement>

<comment>Update admin role</comment>
<statement>
UPDATE roles SET description='The Administrator role' WHERE role='admin';
</statement>
<statement>
UPDATE roles SET admin=1, active=1, builtin=1 WHERE role='admin';
</statement>
<comment>Assign collector, view and service actions permissions to admin role</comment>
<statement>
INSERT INTO rolerow (id, roleid) VALUES (NEXTVAL('tmpseq'), (SELECT id FROM roles WHERE role='admin'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (CURRVAL('tmpseq'), 1);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (CURRVAL('tmpseq'), 2);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (CURRVAL('tmpseq'), 4);
</statement>

<comment>Update monit role and rename it to GUI</comment>
<statement>
UPDATE roles SET role='GUI' WHERE role='monit';
</statement>
<statement>
UPDATE roles SET description='The user role for GUI access' WHERE role='GUI';
</statement>
<statement>
UPDATE roles SET admin=0, active=1, builtin=0 WHERE role='GUI';
</statement>
<comment>Assign view and service actions permissions to GUI role</comment>
<statement>
INSERT INTO rolerow (id, roleid) VALUES (NEXTVAL('tmpseq'), (SELECT id FROM roles WHERE role='GUI'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (CURRVAL('tmpseq'), 2);
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (CURRVAL('tmpseq'), 4);
</statement>

<comment>Add a new collector role (no access to the GUI)</comment>
<statement>
INSERT INTO roles (id, role, description, admin, active, builtin) VALUES (NEXTVAL('tmpseq'), 'collector', 'Collector', 0, 1, 1);
</statement>
<statement>
INSERT INTO rolerow (id, roleid) VALUES (NEXTVAL('tmpseq'), (SELECT id FROM roles WHERE role='collector'));
</statement>
<statement>
INSERT INTO rolerowpermission (rolerowid, permission) VALUES (CURRVAL('tmpseq'), 1);
</statement>

<comment>Add all non-admin users to GUI and collector roles for backward compatibility</comment>
<statement>
DELETE FROM userroles WHERE roleid != (SELECT id FROM roles WHERE role='admin');
</statement>
<statement>
INSERT INTO userroles (userid, roleid) SELECT users.id, roles.id  FROM users, roles WHERE role='GUI';
</statement>
<statement>
INSERT INTO userroles (userid, roleid) SELECT users.id, roles.id  FROM users, roles WHERE role='collector';
</statement>

<comment>Add platformuptime to host table</comment>
<statement>
ALTER TABLE host ADD COLUMN platformuptime BIGINT DEFAULT -1;
</statement>

<comment>Cleanup</comment>
<statement>
DROP SEQUENCE tmpseq;
</statement>

</statements>

</patch>

