pragma foreign_keys = on;

-- Level 0.
create table if not exists Applications(
    id integer primary key autoincrement,
    'name' varchar(64) not null unique, 
    date_in datetime default current_timestamp, 
    date_out datetime null, 
    unique('name')
);

create table if not exists Languages(
    id integer primary key autoincrement,
    'name' varchar(64) not null unique, 
    date_in datetime default current_timestamp, 
    date_out datetime null, 
    unique('name')
);

create table if not exists Files(
    id integer primary key autoincrement,
    'path' varchar(256) not null unique, 
    date_in datetime default current_timestamp, 
    date_out datetime null, 
    unique('path')
);

create table if not exists Traces(
    id integer primary key autoincrement,
    'hash' varchar(256) not null,
    trace text not null,
    date_in datetime default current_timestamp, 
    date_out datetime null, 
    unique('hash')
);

create table if not exists Messages(
    id integer primary key autoincrement,
    'hash' varchar(256) not null,
    'message' text not null,
    date_in datetime default current_timestamp, 
    date_out datetime null, 
    unique('hash')
);

create table if not exists Parameters(
    id integer primary key autoincrement,
    'hash' varchar(256) not null,
    'data' text not null,
    date_in datetime default current_timestamp, 
    date_out datetime null, 
    unique('hash')
);

-- Level 1.
create table if not exists Methods(
    id integer primary key autoincrement,
    'application' integer not null,
    'language' integer not null,
    'file' integer null,
    'name' varchar(64) not null, 
    date_in datetime default current_timestamp, 
    date_out datetime null, 
    foreign key ('application') references Applications(id) on delete restrict on update restrict, 
    foreign key ('language') references Languages(id) on delete restrict on update restrict, 
    foreign key ('file') references Files(id) on delete restrict on update restrict
);

-- Level 2.
create table if not exists Logs(
    id integer primary key autoincrement,
    'method' integer not null,
    'message' integer not null,
    parameters integer not null,
    'line' integer not null,
    error integer not null, 
    date_in datetime default current_timestamp, 
    date_out datetime null,
    foreign key ('method') references Methods(id) on delete restrict on update restrict, 
    foreign key ('message') references Messages(id) on delete restrict on update restrict, 
    foreign key (parameters) references Parameters(id) on delete restrict on update restrict
);

create table if not exists Exceptions(
    id integer primary key autoincrement,
    'method' integer not null,
    trace integer not null,
    'message' integer not null,
    exception integer not null,
    parameters integer not null,
    'line' integer not null,
    'status' varchar(16) null,
    date_in datetime default current_timestamp, 
    date_out datetime null,
    foreign key ('method') references Methods(id) on delete restrict on update restrict, 
    foreign key ('trace') references Traces(id) on delete restrict on update restrict,
    foreign key ('message') references Messages(id) on delete restrict on update restrict, 
    foreign key ('exception') references Messages(id) on delete restrict on update restrict,
    foreign key (parameters) references Parameters(id) on delete restrict on update restrict
);

drop view if exists MethodsView;
create view MethodsView as select 
    methods.id as id, 
    languages.id as language_id,
    applications.id as application_id,
    files.id as file_id,
    applications.name as 'application',
    languages.name as 'language',
    files.path as 'file',
    methods.name as 'name'
from Methods methods 
join Applications applications on methods.application = applications.id 
join Languages languages on methods.language = languages.id 
join Files files on methods.file = files.id 
where 
    methods.date_out is null and 
    applications.date_out is null and 
    languages.date_out is null and 
    files.date_out is null;

drop view if exists LogsView;
create view LogsView as select 
    logs.id as id, 
    methods.application as 'application',
    methods.language as 'language',
    methods.file as 'file',
    methods.name as method,
    logs.line as 'line',
    messages.message as 'message',
    parameters.data as parameters,
    logs.error as error,
    logs.date_in as date_in
from Logs logs 
join MethodsView methods on logs.method = methods.id 
join Messages messages on logs.message = messages.id
join Parameters parameters on logs.parameters = parameters.id 
where 
    logs.date_out is null and 
    messages.date_out is null and 
    parameters.date_out is null;

drop view if exists ExceptionsView;
create view ExceptionsView as select 
    exceptions.id as id, 
    methods.application as 'application',
    methods.language as 'language',
    methods.file as 'file',
    methods.name as method,
    exceptions.line as 'line',
    messages.message as 'message',
    traces.trace as 'trace',
    exceptions_message.message as 'exception',
    parameters.data as parameters,
    exceptions.date_in as date_in
from Exceptions exceptions 
join MethodsView methods on exceptions.method = methods.id 
join Messages messages on exceptions.message = messages.id
join Messages exceptions_message on exceptions.exception = exceptions_message.id
join Traces traces on exceptions.trace = traces.id
join Parameters parameters on exceptions.parameters = parameters.id 
where 
    exceptions.date_out is null and 
    messages.date_out is null and 
    exceptions_message.date_out is null and 
    traces.date_out is null and
    parameters.date_out is null;