+--------------------------------------------------------------------------------
+-- Initscripts
+--------------------------------------------------------------------------------
+
+-- Initscripts
+CREATE TABLE initscripts (
+ initscript_id serial PRIMARY KEY, -- Initscript identifier
+ name text NOT NULL, -- Initscript name
+ enabled bool NOT NULL DEFAULT true, -- Initscript is active
+ script text NOT NULL, -- Initscript
+ UNIQUE (name)
+) WITH OIDS;
+CREATE INDEX initscripts_name_idx ON initscripts (name);
+
+
+--------------------------------------------------------------------------------
+-- Peers
+--------------------------------------------------------------------------------
+
+-- Peers
+CREATE TABLE peers (
+ peer_id serial PRIMARY KEY, -- Peer identifier
+ peername text NOT NULL, -- Peer name
+ peer_url text NOT NULL, -- (HTTPS) URL of the peer PLCAPI interface
+ cacert text, -- (SSL) Public certificate of peer API server
+ key text, -- (GPG) Public key used for authentication
+ deleted boolean NOT NULL DEFAULT false
+) WITH OIDS;
+CREATE INDEX peers_peername_idx ON peers (peername) WHERE deleted IS false;
+
+-- Objects at each peer
+CREATE TABLE peer_site (
+ site_id integer REFERENCES sites PRIMARY KEY, -- Local site identifier
+ peer_id integer REFERENCES peers NOT NULL, -- Peer identifier
+ peer_site_id integer NOT NULL, -- Foreign site identifier at peer
+ UNIQUE (peer_id, peer_site_id) -- The same foreign site should not be cached twice
+) WITH OIDS;
+CREATE INDEX peer_site_peer_id_idx ON peers (peer_id);
+
+CREATE VIEW peer_sites AS
+SELECT peer_id,
+array_accum(site_id) AS site_ids,
+array_accum(peer_site_id) AS peer_site_ids
+FROM peer_site
+GROUP BY peer_id;
+
+CREATE TABLE peer_person (
+ person_id integer REFERENCES persons PRIMARY KEY, -- Local user identifier
+ peer_id integer REFERENCES peers NOT NULL, -- Peer identifier
+ peer_person_id integer NOT NULL, -- Foreign user identifier at peer
+ UNIQUE (peer_id, peer_person_id) -- The same foreign user should not be cached twice
+) WITH OIDS;
+CREATE INDEX peer_person_peer_id_idx ON peer_person (peer_id);
+
+CREATE VIEW peer_persons AS
+SELECT peer_id,
+array_accum(person_id) AS person_ids,
+array_accum(peer_person_id) AS peer_person_ids
+FROM peer_person
+GROUP BY peer_id;
+
+CREATE TABLE peer_key (
+ key_id integer REFERENCES keys PRIMARY KEY, -- Local key identifier
+ peer_id integer REFERENCES peers NOT NULL, -- Peer identifier
+ peer_key_id integer NOT NULL, -- Foreign key identifier at peer
+ UNIQUE (peer_id, peer_key_id) -- The same foreign key should not be cached twice
+) WITH OIDS;
+CREATE INDEX peer_key_peer_id_idx ON peer_key (peer_id);
+
+CREATE VIEW peer_keys AS
+SELECT peer_id,
+array_accum(key_id) AS key_ids,
+array_accum(peer_key_id) AS peer_key_ids
+FROM peer_key
+GROUP BY peer_id;
+
+CREATE TABLE peer_node (
+ node_id integer REFERENCES nodes PRIMARY KEY, -- Local node identifier
+ peer_id integer REFERENCES peers NOT NULL, -- Peer identifier
+ peer_node_id integer NOT NULL, -- Foreign node identifier
+ UNIQUE (peer_id, peer_node_id) -- The same foreign node should not be cached twice
+) WITH OIDS;
+CREATE INDEX peer_node_peer_id_idx ON peer_node (peer_id);
+
+CREATE VIEW peer_nodes AS
+SELECT peer_id,
+array_accum(node_id) AS node_ids,
+array_accum(peer_node_id) AS peer_node_ids
+FROM peer_node
+GROUP BY peer_id;
+
+CREATE TABLE peer_slice (
+ slice_id integer REFERENCES slices PRIMARY KEY, -- Local slice identifier
+ peer_id integer REFERENCES peers NOT NULL, -- Peer identifier
+ peer_slice_id integer NOT NULL, -- Slice identifier at peer
+ UNIQUE (peer_id, peer_slice_id) -- The same foreign slice should not be cached twice
+) WITH OIDS;
+CREATE INDEX peer_slice_peer_id_idx ON peer_slice (peer_id);
+
+CREATE VIEW peer_slices AS
+SELECT peer_id,
+array_accum(slice_id) AS slice_ids,
+array_accum(peer_slice_id) AS peer_slice_ids
+FROM peer_slice
+GROUP BY peer_id;
+
+--------------------------------------------------------------------------------
+-- Authenticated sessions
+--------------------------------------------------------------------------------
+
+-- Authenticated sessions
+CREATE TABLE sessions (
+ session_id text PRIMARY KEY, -- Session identifier
+ expires timestamp without time zone
+) WITH OIDS;
+
+-- People can have multiple sessions
+CREATE TABLE person_session (
+ person_id integer REFERENCES persons NOT NULL, -- Account identifier
+ session_id text REFERENCES sessions NOT NULL, -- Session identifier
+ PRIMARY KEY (person_id, session_id),
+ UNIQUE (session_id) -- Sessions are unique
+) WITH OIDS;
+CREATE INDEX person_session_person_id_idx ON person_session (person_id);
+
+-- Nodes can have only one session
+CREATE TABLE node_session (
+ node_id integer REFERENCES nodes NOT NULL, -- Node identifier
+ session_id text REFERENCES sessions NOT NULL, -- Session identifier
+ UNIQUE (node_id), -- Nodes can have only one session
+ UNIQUE (session_id) -- Sessions are unique
+) WITH OIDS;
+
+
+
+-------------------------------------------------------------------------------
+-- PCU Types
+------------------------------------------------------------------------------
+CREATE TABLE pcu_types (
+ pcu_type_id serial PRIMARY KEY,
+ model text NOT NULL , -- PCU model name
+ name text -- Full PCU model name
+) WITH OIDS;
+CREATE INDEX pcu_types_model_idx ON pcu_types (model);
+
+CREATE TABLE pcu_protocol_type (
+ pcu_protocol_type_id serial PRIMARY KEY,
+ pcu_type_id integer REFERENCES pcu_types NOT NULL, -- PCU type identifier
+ port integer NOT NULL, -- PCU port
+ protocol text NOT NULL, -- Protocol
+ supported boolean NOT NULL DEFAULT True -- Does PLC support
+) WITH OIDS;
+CREATE INDEX pcu_protocol_type_pcu_type_id ON pcu_protocol_type (pcu_type_id);
+
+
+CREATE OR REPLACE VIEW pcu_protocol_types AS
+SELECT pcu_type_id,
+array_accum(pcu_protocol_type_id) as pcu_protocol_type_ids
+FROM pcu_protocol_type
+GROUP BY pcu_type_id;
+
+--------------------------------------------------------------------------------
+-- Message templates
+--------------------------------------------------------------------------------
+
+CREATE TABLE messages (
+ message_id text PRIMARY KEY, -- Message name
+ subject text, -- Message summary
+ template text, -- Message template
+ enabled bool NOT NULL DEFAULT true -- Whether message is enabled
+) WITH OIDS;
+
+--------------------------------------------------------------------------------
+-- Events
+--------------------------------------------------------------------------------
+
+-- Events
+CREATE TABLE events (
+ event_id serial PRIMARY KEY, -- Event identifier
+ person_id integer REFERENCES persons, -- Person responsible for event, if any
+ node_id integer REFERENCES nodes, -- Node responsible for event, if any
+ auth_type text, -- Type of auth used. i.e. AuthMethod
+ fault_code integer NOT NULL DEFAULT 0, -- Did this event result in error
+ call_name text NOT NULL, -- Call responsible for this event
+ call text NOT NULL, -- Call responsible for this event, including parameters
+ message text, -- High level description of this event
+ runtime float DEFAULT 0, -- Event run time
+ time timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP -- Event timestamp
+) WITH OIDS;
+
+-- Database object(s) that may have been affected by a particular event
+CREATE TABLE event_object (
+ event_id integer REFERENCES events NOT NULL, -- Event identifier
+ object_id integer NOT NULL, -- Object identifier
+ object_type text NOT NULL Default 'Unknown' -- What type of object is this event affecting
+) WITH OIDS;
+CREATE INDEX event_object_event_id_idx ON event_object (event_id);
+CREATE INDEX event_object_object_id_idx ON event_object (object_id);
+CREATE INDEX event_object_object_type_idx ON event_object (object_type);
+
+CREATE OR REPLACE VIEW event_objects AS
+SELECT event_id,
+array_accum(object_id) AS object_ids,
+array_accum(object_type) AS object_types
+FROM event_object
+GROUP BY event_id;
+