AnPv2/SQLServer/AnP.1.10.common.server.sql

690 lines
26 KiB
Transact-SQL

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