use AnP

if object_id(N'dbo.permissions_tables_remove', N'P') is not null drop procedure dbo.permissions_tables_remove
go
create procedure dbo.permissions_tables_remove as begin set nocount on 

    if object_id(N'dbo._PermissionsGroups', N'U') is not null drop table dbo._PermissionsGroups
    if object_id(N'dbo._Permissions', N'U') is not null drop table dbo._Permissions

    if object_id(N'dbo.PermissionsGroups', N'U') is not null drop table dbo.PermissionsGroups
    if object_id(N'dbo.Permissions', N'U') is not null drop table dbo.Permissions

end
go

if object_id(N'dbo.permissions_tables_create', N'P') is not null drop procedure dbo.permissions_tables_create
go
create procedure dbo.permissions_tables_create as begin set nocount on 

    if object_id(N'dbo.Permissions', N'U') is null create table dbo.Permissions(
        id integer not null identity(1, 1), 
        [procedure] integer not null, 
        [session] integer not null, 
        [name] varchar(64) not null, 
        [description] varchar(512) not null, 
        date_in datetime not null constraint df_permissions_date_in default getdate(), 
        date_out datetime, 
        constraint pk_permissions primary key clustered(id), 
        constraint fk_permissions_procedure foreign key([procedure]) references dbo.Procedures(id) 
            on update no action 
            on delete no action,
        constraint fk_permissions_session foreign key([session]) references dbo.Sessions(id) 
            on update no action 
            on delete no action,
        constraint uq_permissions_name unique([name]) with(fillfactor = 90), 
        constraint ck_permissions_name check([name] != '' and [name] not like '%[^a-zA-Z0-9_]%' and [name] not like '[^a-zA-Z_]%')
    )

    if object_id(N'dbo.PermissionsGroups', N'U') is null create table dbo.PermissionsGroups(
        id integer not null identity(1, 1), 
        [procedure] integer not null, 
        [session] integer not null, 
        permission integer not null, 
        [group] integer not null,
        belongs bit not null constraint df_permissions_groups_belongs default 1,
        date_in datetime not null constraint df_permissions_groups_date_in default getdate(), 
        date_out datetime, 
        constraint pk_permissions_groups primary key clustered(id), 
        constraint fk_permissions_groups_procedure foreign key([procedure]) references dbo.Procedures(id) 
            on update no action 
            on delete no action,
        constraint fk_permissions_groups_session foreign key([session]) references dbo.Sessions(id) 
            on update no action 
            on delete no action, 
        constraint fk_permissions_groups_permission foreign key(permission) references dbo.Permissions(id) 
            on update no action 
            on delete no action,
        constraint fk_permissions_groups_group foreign key([group]) references dbo.Groups(id) 
            on update no action
            on delete no action, 
        constraint uq_permissions_groups unique(permission, [group]) with(fillfactor = 90)
    )

    if object_id(N'dbo._Permissions', N'U') is null create table dbo._Permissions(
        id integer not null identity(1, 1), 
        history_mode integer not null, 
        entity integer not null, 
        [procedure] integer not null, 
        [session] integer not null, 
        [name] varchar(64) not null, 
        [description] varchar(512) not null, 
        date_in datetime not null, 
        date_out datetime, 
        constraint pk__permissions primary key clustered(id), 
        constraint fk__permissions_history_mode foreign key(history_mode) references dbo.HistoryModes(id) 
            on update no action 
            on delete no action,
        constraint fk__permissions_procedure foreign key([procedure]) references dbo.Procedures(id) 
            on update no action 
            on delete no action,
        constraint fk__permissions_session foreign key([session]) references dbo.Sessions(id) 
            on update no action 
            on delete no action
    )

    if object_id(N'dbo._PermissionsGroups', N'U') is null create table dbo._PermissionsGroups(
        id integer not null identity(1, 1), 
        history_mode integer not null,
        entity integer not null, 
        [procedure] integer not null, 
        [session] integer not null, 
        permission integer not null, 
        [group] integer not null,
        belongs bit not null,
        date_in datetime not null, 
        date_out datetime, 
        constraint pk__permissions_groups primary key clustered(id), 
        constraint fk__permissions_groups_history_mode foreign key(history_mode) references dbo.HistoryModes(id) 
            on update no action 
            on delete no action,
        constraint fk__permissions_groups_procedure foreign key([procedure]) references dbo.Procedures(id) 
            on update no action 
            on delete no action,
        constraint fk__permissions_groups_session foreign key([session]) references dbo.Sessions(id) 
            on update no action 
            on delete no action, 
        constraint fk__permissions_groups_permission foreign key(permission) references dbo.Permissions(id) 
            on update no action 
            on delete no action,
        constraint fk__permissions_groups_group foreign key([group]) references dbo.Groups(id) 
            on update no action
            on delete no action
    )

end
go

execute dbo.permissions_tables_create

if object_id(N'dbo.permissions_trigger', N'TR') is not null drop trigger dbo.permissions_trigger
go
create trigger dbo.permissions_trigger on dbo.Permissions for insert, update, delete as begin set nocount on 

    declare @insert integer, @update integer, @delete integer, @unknown integer

    execute dbo.history_mode_get @insert output, @update output, @delete output, @unknown output

    -- update.
    insert into dbo._Permissions(history_mode, entity, [procedure], [session], [name], [description], date_in, date_out) 
    select @update, inserted.id, inserted.[procedure], inserted.[session], inserted.[name], inserted.[description], inserted.date_in, inserted.date_out 
    from inserted inserted 
    join deleted deleted on inserted.id = deleted.id 
    where 
        inserted.[procedure] != deleted.[procedure] or 
        inserted.[session] != deleted.[session] or 
        inserted.[name] != deleted.[name] or 
        inserted.[description] != deleted.[description] or 
        inserted.date_in != deleted.date_in or 
        isnull(inserted.date_out, '0001-01-01') != isnull(deleted.date_out, '0001-01-01')

    -- Insert.
    insert into dbo._Permissions(history_mode, entity, [procedure], [session], [name], [description], date_in, date_out) 
    select @insert, inserted.id, inserted.[procedure], inserted.[session], inserted.[name], inserted.[description], inserted.date_in, inserted.date_out 
    from inserted inserted 
    left join deleted deleted on inserted.id = deleted.id 
    where deleted.id is null

    -- deleted.
    insert into dbo._Permissions(history_mode, entity, [procedure], [session], [name], [description], date_in, date_out) 
    select @delete, deleted.id, deleted.[procedure], deleted.[session], deleted.[name], deleted.[description], deleted.date_in, deleted.date_out 
    from deleted deleted 
    left join inserted inserted on deleted.id = inserted.id 
    where inserted.id is null

end
go

if object_id(N'dbo.permissions_groups_trigger', N'TR') is not null drop trigger dbo.permissions_groups_trigger
go
create trigger dbo.permissions_groups_trigger on dbo.PermissionsGroups for insert, update, delete as begin set nocount on 

    declare @insert integer, @update integer, @delete integer, @unknown integer

    execute dbo.history_mode_get @insert output, @update output, @delete output, @unknown output

    -- update.
    insert into dbo._PermissionsGroups(history_mode, entity, [procedure], [session], [permission], [group], belongs, date_in, date_out) 
    select @update, inserted.id, inserted.[procedure], inserted.[session], inserted.[permission], inserted.[group], inserted.belongs, inserted.date_in, inserted.date_out 
    from inserted inserted 
    join deleted deleted on inserted.id = deleted.id 
    where 
        inserted.[procedure] != deleted.[procedure] or 
        inserted.[session] != deleted.[session] or 
        inserted.[permission] != deleted.[permission] or 
        inserted.[group] != deleted.[group] or 
        inserted.belongs != deleted.belongs or 
        inserted.date_in != deleted.date_in or 
        isnull(inserted.date_out, '0001-01-01') != isnull(deleted.date_out, '0001-01-01')

    -- Insert.
    insert into dbo._PermissionsGroups(history_mode, entity, [procedure], [session], [permission], [group], belongs, date_in, date_out) 
    select @insert, inserted.id, inserted.[procedure], inserted.[session], inserted.[permission], inserted.[group], inserted.belongs, inserted.date_in, inserted.date_out 
    from inserted inserted 
    left join deleted deleted on inserted.id = deleted.id 
    where deleted.id is null

    -- deleted.
    insert into dbo._PermissionsGroups(history_mode, entity, [procedure], [session], [permission], [group], belongs, date_in, date_out) 
    select @delete, deleted.id, deleted.[procedure], deleted.[session], deleted.[permission], deleted.[group], deleted.belongs, deleted.date_in, deleted.date_out 
    from deleted deleted 
    left join inserted inserted on deleted.id = inserted.id 
    where inserted.id is null

end
go