if (select top 1 0 from sys.databases where name = 'AnP') is null create database AnP collate Latin1_General_CI_AS go use AnP if object_id(N'dbo.common_tables_delete', N'P') is not null drop procedure dbo.common_tables_delete go create procedure dbo.common_tables_delete as begin set nocount on if object_id(N'dbo.fk_sessions_user', N'F') is not null alter table dbo.[Sessions] drop constraint fk_sessions_user -- Level 3. if object_id(N'dbo.Logs', N'U') is not null drop table dbo.Logs if object_id(N'dbo.Exceptions', N'U') is not null drop table dbo.Exceptions if object_id(N'dbo.Terminals', N'U') is not null drop table dbo.Terminals if object_id(N'dbo.SessionsIps', N'U') is not null drop table dbo.SessionsIps -- Level 2. if object_id(N'dbo.[Sessions]', N'U') is not null drop table dbo.[Sessions] -- Level 1. if object_id(N'dbo.[Procedures]', N'U') is not null drop table dbo.[Procedures] if object_id(N'dbo.Users', N'U') is not null drop table dbo.Users -- Level 0. if object_id(N'dbo.Ips', N'U') is not null drop table dbo.Ips if object_id(N'dbo.[Databases]', N'U') is not null drop table dbo.[Databases] if object_id(N'dbo.Hashes', N'U') is not null drop table dbo.Hashes if object_id(N'dbo.[Messages]', N'U') is not null drop table dbo.[Messages] if object_id(N'dbo.Errors', N'U') is not null drop table dbo.Errors -- Level historical. if object_id(N'dbo.UsersData', N'U') is not null drop table dbo.UsersData end go if object_id(N'dbo.common_tables_create', N'P') is not null drop procedure dbo.common_tables_create go create procedure dbo.common_tables_create as begin set nocount on -- Level historical. if object_id(N'dbo.UsersData', N'U') is null create table dbo.UsersData( id integer not null identity(1, 1), entity integer not null, [procedure] integer not null, [session] integer not null, [hash] integer, nick varchar(32) collate database_default, [password] binary(64), accessible bit, date_in datetime not null, date_out datetime, constraint pk_users_data primary key clustered (id) ) -- Level 0. if object_id(N'dbo.[Databases]', N'U') is null create table dbo.[Databases]( id integer not null identity(1, 1), [name] varchar(64) collate database_default not null, date_in datetime not null constraint df_databases_date_in default getdate(), date_out datetime, constraint pk_databases primary key clustered (id), constraint uk_databases_name unique nonclustered ([name] asc) with (fillfactor = 90), constraint ck_databases_name check ( [name] != '' and [name] like '[a-z_]%' and [name] not like '%[^a-z0-9_]%' ) ) if object_id(N'dbo.[Messages]', N'U') is null create table dbo.[Messages]( id integer not null identity(1, 1), [message] varchar(max) collate database_default not null, date_in datetime not null constraint df_messages_date_in default getdate(), date_out datetime, constraint pk_messages primary key clustered (id) ) if object_id(N'dbo.Hashes', N'U') is null create table dbo.Hashes( id integer not null identity(1, 1), [name] varchar(16) collate database_default not null, date_in datetime not null constraint df_hashes_date_in default getdate(), date_out datetime, constraint pk_hashes primary key clustered (id), constraint uk_hashes_name unique nonclustered ([name] asc) with (fillfactor = 90), constraint ck_hashes_name check ([name] != '') ) if object_id(N'dbo.Errors', N'U') is null create table dbo.Errors( id integer not null identity(1, 1), [error] varchar(512) collate database_default not null, date_in datetime not null constraint df_errors_date_in default getdate(), date_out datetime, constraint pk_errors primary key clustered (id), constraint uk_errors_error unique nonclustered ([error] asc) with (fillfactor = 90) ) create table dbo.Ips( id integer not null identity(1, 1), [ip] varchar(45) collate database_default not null, -- 3x4+3=15 for IPv4; 8x4+7=39 for IPv6; 30+15 for Hibrid. date_in datetime not null constraint df_ips_date_in default getdate(), date_out datetime, constraint pk_ips primary key clustered (id), constraint uk_ips_ip unique nonclustered ([ip] asc) with (fillfactor = 90), constraint ck_ips_ip check (len([ip]) > 1 and [ip] not like '%[^0-9a-f:.]%'), index ix_ips_ip nonclustered ([ip] asc) with (fillfactor = 90) ) -- Level 1. if object_id(N'dbo.[Procedures]', N'U') is null begin create table dbo.[Procedures]( id integer not null identity(1, 1), [database] integer not null, [name] varchar(64) collate database_default not null, date_in datetime not null constraint df_procedures_date_in default getdate(), date_out datetime, constraint pk_procedures primary key clustered (id), constraint fk_procedures_database foreign key([database]) references dbo.[Databases](id), constraint uk_procedures_name unique([database], [name]), constraint ck_procedures_database check ([database] > 0), constraint ck_procedures_name check ( [name] != '' and [name] like '[a-z_]%' and [name] not like '%[^a-z0-9_]%' ) ) create nonclustered index ix_procedures_name on dbo.[Procedures]([name] asc) include ([database]) with (fillfactor = 90) end if object_id(N'dbo.Users', N'U') is null create table dbo.Users( id integer not null identity(1, 1), [hash] integer not null constraint df_users_hash default 1, nick varchar(32) collate database_default not null, [password] binary(64), accessible bit not null constraint df_users_accessible default 1, date_in datetime not null constraint df_users_date_in default getdate(), date_out datetime, constraint pk_users_id primary key clustered (id), constraint fk_users_hash foreign key([hash]) references dbo.Hashes(id), constraint uk_users_nick unique nonclustered (nick asc) with (fillfactor = 90), constraint ck_users_hash check ([hash] > 0), constraint ck_users_nick check (nick != ''), index ix_users_hash nonclustered ([hash] asc) with (fillfactor = 90), index ix_users_nick nonclustered (nick asc) with (fillfactor = 90) ) -- level 2. if object_id(N'dbo.[Sessions]', N'U') is null create table dbo.[Sessions]( id integer not null identity(1, 1), [user] integer not null, date_last datetime not null constraint df_sessions_date_last default getdate(), date_in datetime not null constraint df_sessions_date_in default getdate(), date_out datetime, constraint pk_sessions primary key clustered (id), constraint fk_sessions_user foreign key([user]) references dbo.Users(id), constraint ck_sessions_user check ([user] > 0), index ix_sessions_user nonclustered ([user] asc) with (fillfactor = 90) ) -- Level 3. if object_id(N'dbo.Logs', N'U') is null begin create table dbo.Logs( id integer not null identity(1, 1), [procedure] integer not null, [session] integer not null, [message] integer not null, error integer, parameters text, date_in datetime not null constraint df_logs_date_in default getdate(), date_out datetime, constraint pk_logs primary key clustered (id), constraint fk_logs_procedure foreign key([procedure]) references dbo.[Procedures](id), constraint fk_logs_session foreign key([session]) references dbo.[Sessions](id), constraint fk_logs_message foreign key([message]) references dbo.[Messages](id), constraint fk_logs_error foreign key(error) references dbo.Errors(id), constraint ck_logs_procedure check ([procedure] > 0), constraint ck_logs_session check ([session] > 0), constraint ck_logs_message check ([message] > 0), constraint ck_logs_error check (error is null or error > 0) ) create nonclustered index ix_logs_procedure on dbo.Logs ([procedure] asc) include ([session], [message], error) with (fillfactor = 90) create nonclustered index ix_logs_session on dbo.Logs ([session] asc) include ([procedure], [message], error) with (fillfactor = 90) create nonclustered index ix_logs_error on dbo.Logs (error asc) include ([procedure], [session], [message]) with (fillfactor = 90) create nonclustered index ix_logs_message on dbo.Logs ([message] asc) include ([procedure], [session], error) with (fillfactor = 90) end if object_id(N'dbo.Exceptions', N'U') is null begin create table dbo.Exceptions( id integer not null identity(1, 1), [procedure] integer not null, [session] integer not null, [message] integer not null, exception integer not null, parameters text, [status] varchar(16) collate database_default, code integer, date_in datetime not null constraint df_exceptions_date_in default getdate(), date_out datetime, constraint pk_exceptions primary key clustered (id), constraint fk_exceptions_procedure foreign key([procedure]) references dbo.[Procedures](id), constraint fk_exceptions_session foreign key([session]) references dbo.[Sessions](id), constraint fk_exceptions_message foreign key([message]) references dbo.[Messages](id), constraint fk_exceptions_exception foreign key([exception]) references dbo.[Messages](id), constraint ck_exceptions_procedure check ([procedure] > 0), constraint ck_exceptions_session check ([session] > 0), constraint ck_exceptions_message check ([message] > 0), constraint ck_exceptions_exception check ([exception] > 0) ) create nonclustered index ix_exceptions_procedure on dbo.Exceptions ([procedure] asc) include ([session], [message], exception) with (fillfactor = 90) create nonclustered index ix_exceptions_session on dbo.Exceptions ([session] asc) include ([procedure], [message], exception) with (fillfactor = 90) create nonclustered index ix_exceptions_exception on dbo.Exceptions (exception asc) include ([procedure], [session], [message]) with (fillfactor = 90) create nonclustered index ix_exceptions_message on dbo.Exceptions ([message] asc) include ([procedure], [session], exception) with (fillfactor = 90) end if object_id(N'dbo.Terminals', N'U') is null begin create table dbo.Terminals( id integer not null identity(1, 1), [procedure] integer not null, [session] integer not null, [message] varchar(max) collate database_default, date_in datetime not null constraint df_terminals_date_in default getdate(), date_out datetime, constraint pk_terminals_id primary key clustered (id), constraint fk_terminals_procedure foreign key([procedure]) references dbo.[Procedures](id), constraint fk_terminals_session foreign key([session]) references dbo.[Sessions](id), constraint ck_terminals_procedure check ([procedure] > 0), constraint ck_terminals_session check ([session] > 0) ) create nonclustered index ix_terminals_procedure on dbo.Terminals ([procedure] asc) include ([session]) with (fillfactor = 90) create nonclustered index ix_terminals_session on dbo.Terminals ([session] asc) include ([procedure]) with (fillfactor = 90) end if object_id(N'dbo.SessionsIps', N'U') is null begin create table dbo.SessionsIps( id integer not null identity(1, 1), [session] integer not null, [ip] integer not null, date_in datetime not null constraint df_sessions_ips_date_in default getdate(), date_out datetime, constraint pk_sessions_ips_id primary key clustered (id), constraint fk_sessions_ips_session foreign key([session]) references dbo.[Sessions](id), constraint fk_sessions_ips_ip foreign key([ip]) references dbo.Ips(id), constraint ck_sessions_ips_session check ([session] > 0), constraint ck_sessions_ips_ip check ([ip] > 0) ) create nonclustered index ix_sessions_ips_session on dbo.SessionsIps ([session] asc) include ([ip]) with (fillfactor = 90) create nonclustered index ix_sessions_ips_ip on dbo.SessionsIps ([ip] asc) include ([session]) with (fillfactor = 90) end end go if object_id(N'dbo.common_tables_update', N'P') is not null drop procedure dbo.common_tables_update go create procedure dbo.common_tables_update as begin set nocount on end go execute dbo.common_tables_delete go execute dbo.common_tables_create go execute dbo.common_tables_update go if object_id(N'dbo.sql_set', N'P') is not null drop procedure dbo.sql_set go create procedure dbo.sql_set @database varchar(64), @procedure varchar(64), @session integer as begin declare @data binary(128) = ( cast(substring(isnull(@database, ''), 1, 62) as binary(62)) + cast(substring(isnull(@procedure, ''), 1, 62) as binary(62)) + cast(isnull(@session, 0) as binary(4)) ) set nocount on set context_info @data end go if object_id(N'dbo.sql_get', N'P') is not null drop procedure dbo.sql_get go create procedure dbo.sql_get @database varchar(64) output, @procedure varchar(64) output, @session integer output as begin declare @context binary(128) = context_info() declare @null char(1) = char(0) set nocount on set @database = rtrim(replace(cast(substring(@context, 1, 62) as varchar(64)), @null, '')) set @procedure = rtrim(replace(cast(substring(@context, 63, 62) as varchar(64)), @null, '')) set @session = cast(substring(@context, 125, 4) as int) end go if object_id(N'dbo.procedure_get', N'P') is not null drop procedure dbo.procedure_get go create procedure dbo.procedure_get @database varchar(64), @procedure varchar(64), @id integer output as begin declare @database_id integer = (select top 1 id from dbo.[Databases] where date_out is null and [name] = @database ) set nocount on if @database_id is null begin insert into dbo.[Databases]([name]) values(@database) set @database_id = scope_identity() end set @id = (select top 1 id from dbo.[Procedures] where date_out is null and [database] = @database_id and [name] = @procedure ) if @id is null begin insert into dbo.[Procedures]([database], [name]) values(@database_id, @procedure) set @id = scope_identity() end end go if object_id(N'dbo.users_trigger_update', N'TR') is not null drop trigger dbo.users_trigger_update go create trigger dbo.users_trigger_update on dbo.Users after insert, update as begin declare @session integer declare @database varchar(64) declare @procedure varchar(64) declare @procedure_id integer declare @id integer declare @hash integer declare @nick varchar(32) declare @password binary(64) declare @accessible bit declare @date_in datetime declare @date_out datetime declare users_cursor cursor local for ( select id, [hash], nick, [password], accessible, date_in, date_out from inserted ) set nocount on execute dbo.sql_get @database output, @procedure output, @session output execute dbo.procedure_get @database, @procedure, @procedure_id output open users_cursor while 1 = 1 begin fetch next from users_cursor into @id, @hash, @nick, @password, @accessible, @date_in, @date_out if @@fetch_status != 0 break insert into dbo.UsersData(entity, [procedure], [session], [hash], nick, [password], accessible, date_in, date_out) values (@id, @procedure_id, @session, @hash, @nick, @password, @accessible, @date_in, @date_out) end close users_cursor deallocate users_cursor end go if object_id(N'dbo.hash_create_name', N'FN') is not null drop function dbo.hash_create_name go create function dbo.hash_create_name( @method varchar(16) ) returns varchar(16) as begin return (case when @method = 'md5' then 'md5' when @method = 'sha1' then 'sha1' when @method in ( 'sha2_256', 'sha2-256', 'sha-256', 'sha256', 'sha_256' ) then 'sha2_256' when @method in ( 'sha2_512', 'sha2-512', 'sha-512', 'sha512', 'sha_512' ) then 'sha2_512' else null end) end go if object_id(N'dbo.hash_create', N'FN') is not null drop function dbo.hash_create go create function dbo.hash_create( @method varchar(16), @input varchar(max) ) returns binary(64) as begin set @method = dbo.hash_create_name(@method) return (case when @method in ( 'md5', 'sha1', 'sha2_256', 'sha2_512' ) then hashbytes(upper(@method), @input) else cast(@input as binary(64)) end) end go if object_id(N'dbo.message_get', N'P') is not null drop procedure dbo.message_get go create procedure dbo.message_get @message varchar(max), @id integer output as begin set nocount on set @id = (select top 1 id from dbo.[Messages] where date_out is null and [message] = @message) if @id is null begin insert into dbo.[Messages]([message]) values(@message) set @id = scope_identity() end end go if object_id(N'dbo.error_get', N'P') is not null drop procedure dbo.error_get go create procedure dbo.error_get @error varchar(512), @id integer output as begin set nocount on set @id = (select top 1 id from dbo.Errors where date_out is null and [error] = @error) if @id is null begin insert into dbo.Errors([error]) values(@error) set @id = scope_identity() end end go if object_id(N'dbo.hash_get', N'P') is not null drop procedure dbo.hash_get go create procedure dbo.hash_get @name varchar(16), @id integer output as begin set nocount on set @id = (select top 1 id from dbo.Hashes where date_out is null and [name] = @name) if @id is null begin insert into dbo.Hashes([name]) values(@name) set @id = scope_identity() end end go if object_id(N'dbo.logs_set', N'P') is not null drop procedure dbo.logs_set go create procedure dbo.logs_set @session integer, @database varchar(64), @procedure varchar(64), @message varchar(max), @parameters varchar(max), @error varchar(512) = '', @level tinyint = 0 as begin declare @procedure_id integer declare @error_id integer declare @message_id integer set nocount on execute dbo.procedure_get @database, @procedure, @procedure_id output execute dbo.message_get @message, @message_id output execute dbo.error_get @error, @error_id output insert into dbo.Logs([procedure], [session], [message], parameters, [error]) values (@procedure_id, @session, @message_id, @parameters, @error_id) end go if object_id(N'dbo.logs_set', N'P') is not null drop procedure dbo.logs_set go create procedure dbo.logs_set @session integer, @database varchar(64), @procedure varchar(64), @message varchar(max), @parameters varchar(max) as begin declare @exception varchar(max) = error_message() declare @status varchar(16) = error_state() declare @code integer = error_number() declare @exception_id integer declare @procedure_id integer declare @message_id integer set nocount on execute dbo.message_get @exception, @exception_id output execute dbo.procedure_get @database, @procedure, @procedure_id output execute dbo.message_get @message, @message_id output insert into dbo.Exceptions([procedure], [session], [message], exception, [parameters], [status], code) values (@procedure_id, @session, @message_id, @exception_id, @parameters, @status, @code) end go if object_id(N'dbo.common_tables_fill', N'P') is not null drop procedure dbo.common_tables_fill go create procedure dbo.common_tables_fill as begin declare @database varchar(64) = 'AnP' declare @procedure varchar(64) = 'common_tables_fill' declare @procedure_id integer declare @local_ip varchar(71) = '::1' declare @main_user varchar(32) = 'machine' declare @user varchar(32) declare @session_id integer = ( select top 1 id from dbo.[Sessions] where date_out is null and [user] = ( select top 1 id from dbo.Users where date_out is null and nick = @main_user ) ) declare @has_session bit = case when @session_id is null then 0 else 1 end declare @ip_id integer = ( select top 1 id from dbo.Ips where date_out is null and ip = @local_ip ) declare @hash_id integer declare @hash varchar(16) declare users_cursor cursor local for ( select @main_user as [name] union all select 'guest' ) declare hashes_cursor cursor local for ( select 'null' as [name] union all select 'md5' union all select 'sha1' union all select 'sha2_256' union all select 'sha2_512' ) set nocount on if @has_session = 0 begin if (select top 1 0 from sys.indexes where name = N'ix_sessions_user') is not null drop index ix_sessions_user on dbo.[Sessions] if object_id(N'dbo.fk_sessions_user', N'F') is not null alter table dbo.[Sessions] drop constraint fk_sessions_user alter table dbo.[Sessions] alter column [user] integer insert into dbo.[Sessions] default values set @session_id = scope_identity() end execute dbo.sql_set @database, @procedure, @session_id execute dbo.procedure_get @database, @procedure, @procedure_id output open hashes_cursor while 1 = 1 begin fetch next from hashes_cursor into @hash if @@fetch_status != 0 break if (select top 1 0 from dbo.Hashes where date_out is null and [name] = @hash) is null insert into dbo.Hashes([name]) values(@hash) end close hashes_cursor deallocate hashes_cursor execute dbo.hash_get 'null', @hash_id output open users_cursor while 1 = 1 begin fetch next from users_cursor into @user if @@fetch_status != 0 break if (select top 1 0 from dbo.Users where date_out is null and nick = @user) is null insert into dbo.Users([hash], nick) values (@hash_id, @user) end close users_cursor deallocate users_cursor if @has_session = 0 begin update dbo.[Sessions] set [user] = ( select top 1 id from dbo.Users where date_out is null and nick = @main_user ) where id = @session_id alter table dbo.[Sessions] alter column [user] integer not null alter table dbo.[Sessions] add constraint fk_sessions_user foreign key([user]) references dbo.Users(id) create nonclustered index ix_sessions_user on dbo.[Sessions]([user] asc) with (fillfactor = 90) end if @ip_id is null begin insert into dbo.Ips([ip]) values(@local_ip) set @ip_id = scope_identity() end if (select top 1 0 from dbo.SessionsIps where date_out is null and [session] = @session_id and [ip] = @ip_id ) is null insert into dbo.SessionsIps([session], [ip]) values(@session_id, @ip_id) end go execute dbo.common_tables_fill go if object_id(N'dbo.where_set', N'FN') is not null drop function dbo.where_set go create function dbo.where_set( @old_where varchar(max), @new_where varchar(max) ) returns varchar(max) as begin set @new_where = ltrim(rtrim(isnull(@new_where, ''))) set @old_where = ltrim(rtrim(isnull(@old_where, ''))) return (case when @new_where = '' then @old_where when @old_where = '' then @new_where else '(' + @old_where + ') and (' + @new_where + ')' end) end go if object_id(N'dbo.tables_list', N'P') is not null drop procedure dbo.tables_list go create procedure dbo.tables_list @view varchar(max), @page integer, @items_per_page integer, @where varchar(max), @order_by varchar(max), @has_errors bit, @pages integer output, @items integer output, @results integer output as begin declare @where_string varchar(max) = (case when @has_errors = 1 then ' where ' + dbo.where_set('0 = 1', @where) when ltrim(rtrim(isnull(@where, ''))) = '' then '' else ' where ' + @where end) declare @query varchar(max) = N'select top 1 @subitems = count(1) from ' + @view + @where_string set nocount on execute sp_executesql @query, N'@subitems integer output', @subitems = @items output set @pages = ceiling(@items / cast(@items_per_page as float)) set @query = ( N'select * from ' + @view + @where_string + (case when ltrim(rtrim(isnull(@order_by, ''))) = '' then '' else N' order by ' + @order_by end) + N' offset ' + cast((((case when @page < 1 then 1 when @page > @pages then @pages else @page end) - 1) * @items_per_page) as varchar) + N' rows fetch next ' + cast(@items_per_page as varchar) + N' rows only' ) execute sp_executesql @query set @results = @@rowcount end go