if (select top 1 0 from sys.databases where name = 'ErrorsManager') is null create database ErrorsManager collate Latin1_General_CI_AS go use ErrorsManager if object_id(N'dbo.tables_drop', N'P') is not null drop procedure dbo.tables_drop go create procedure dbo.tables_drop as begin set nocount on -- Level 1. if object_id(N'dbo.Settings', N'U') is not null drop table dbo.Settings -- Level 0. if object_id(N'dbo.Sets', N'U') is not null drop table dbo.Sets if object_id(N'dbo.Types', N'U') is not null drop table dbo.Types if object_id(N'dbo.Messages', N'U') is not null drop table dbo.Messages end go if object_id(N'dbo.tables_create', N'P') is not null drop procedure dbo.tables_create go create procedure dbo.tables_create as begin set nocount on -- Level 0. if object_id(N'dbo.Sets', N'U') is null create table dbo.Sets( id int not null identity(1, 1), [key] varchar(32) not null, alphabet varchar(128) collate Latin1_General_CS_AS not null, base smallint not null, power tinyint not null, in_use bit not null constraint sets_df_in_use default 0, [description] varchar(512), date_in datetime not null constraint sets_df_date_in default getdate(), last_selection datetime, date_out datetime, constraint sets_pk primary key clustered (id), constraint sets_uk_key unique nonclustered ([key]) with (fillfactor = 90), constraint sets_uk_data unique nonclustered (alphabet, base, power) with (fillfactor = 90), constraint sets_ck_key check ( [key] not like '%[^a-zA-Z0-9_]%' and len([key]) > 0 and len([key]) <= 32 ), constraint sets_ck_alphabet check ( datalength(alphabet) >= 2 and datalength(alphabet) <= 128 ), constraint sets_ck_base check (base >= 2 and base <= 128), constraint sets_ck_power check (power > 0 and power < 8) ) if object_id(N'dbo.Types', N'U') is null create table dbo.Types( id int not null identity(1, 1), [name] varchar(32) not null, [description] varchar(512), date_in datetime not null constraint types_df_date_in default getdate(), date_out datetime, constraint types_pk primary key clustered (id), constraint types_uk_name unique nonclustered ([name]) with (fillfactor = 90), constraint types_ck_name check ( [name] not like '%[^a-zA-Z0-9_]%' and len([name]) > 0 and len([name]) <= 32 ) ) if object_id(N'dbo.Messages', N'U') is null create table dbo.Messages( id int not null identity(1, 1), [bit] smallint not null, [message] varchar(64) not null, date_in datetime not null constraint messages_df_date_in default getdate(), date_out datetime, constraint messages_pk primary key clustered (id), constraint messages_uk_data unique nonclustered ([bit], [message]) with (fillfactor = 90) ) -- Level 1. if object_id(N'dbo.Settings', N'U') is null create table dbo.Settings( id int not null identity(1, 1), [type] integer not null, [key] varchar(32) not null, [value] varchar(128), [description] varchar(512), date_in datetime not null constraint settings_df_date_in default getdate(), date_out datetime, constraint settings_pk primary key clustered (id), constraint settings_fk_type foreign key ([type]) references dbo.Types(id) on update no action on delete no action, constraint settings_uk_key unique nonclustered ([key]) with (fillfactor = 90), constraint settings_ck_key check ( [key] not like '%[^a-zA-Z0-9_]%' and len([key]) > 0 and len([key]) <= 32 ) ) end go if object_id(N'dbo.tables_update', N'P') is not null drop procedure dbo.tables_update go create procedure dbo.tables_update as begin set nocount on declare @database varchar(64) = db_name() -- Level 0. if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'key') is null alter table dbo.Sets add [key] varchar(32) not null, constraint sets_uk_key unique nonclustered ([key]) with (fillfactor = 90), constraint sets_ck_key check ( [key] not like '%[^a-zA-Z0-9_]%' and len([key]) > 0 and len([key]) <= 32 ) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'alphabet') is null alter table dbo.Sets add alphabet varchar(128) not null, constraint sets_ck_alphabet check ( datalength(alphabet) >= 2 and datalength(alphabet) <= 128 ) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'base') is null alter table dbo.Sets add base smallint not null, constraint sets_ck_base check (base >= 2 and base <= 128) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'power') is null alter table dbo.Sets add power tinyint not null, constraint sets_ck_power check (power > 0 and power < 8) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'in_use') is null alter table dbo.Sets add in_use bit not null constraint sets_df_in_use default 0 if (select top 1 0 from information_schema.constraints where table_catalog = @database and table_name = 'Sets' and constraint_name = 'sets_uk_data') is null alter table dbo.Sets add constraint sets_uk_data unique nonclustered (alphabet, base, power) with (fillfactor = 90) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Types' and column_name = 'name') is null alter table dbo.Types add [name] varchar(32) not null, constraint types_uk_name unique nonclustered ([name]) with (fillfactor = 90), constraint types_ck_name check ( [name] not like '%[^a-zA-Z0-9_]%' and len([name]) > 0 and len([name]) <= 32 ) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Types' and column_name = 'description') is null alter table dbo.Types add [description] varchar(512) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Messages' and column_name = 'bit') is null alter table dbo.Messages add [bit] smallint not null if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Messages' and column_name = 'message') is null alter table dbo.Messages add [message] varchar(64) not null if (select top 1 0 from information_schema.constraints where table_catalog = @database and table_name = 'Messages' and constraint_name = 'messages_uk_data') is null alter table dbo.Messages add constraint messages_uk_data unique nonclustered ([bit], [message]) with (fillfactor = 90) -- Level 1. if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Settings' and column_name = 'key') is null alter table dbo.Settings add [key] varchar(32) not null, constraint settings_uk_key unique nonclustered ([key]) with (fillfactor = 90), constraint settings_ck_key check ( [key] not like '%[^a-zA-Z0-9_]%' and len([key]) > 0 and len([key]) <= 32 ) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Settings' and column_name = 'value') is null alter table dbo.Settings add [value] varchar(128) if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Settings' and column_name = 'description') is null alter table dbo.Settings add [description] varchar(512) end go if object_id(N'dbo.tables_fill', N'P') is not null drop procedure dbo.tables_fill go create procedure dbo.tables_fill as begin set nocount on if object_id(N'tempdb..#Settings', N'U') is not null drop table #Settings create table #Settings( [type] varchar(32) not null, [key] varchar(32) not null, [value] varchar(128) ) if object_id(N'tempdb..#Messages', N'U') is not null drop table #Messages create table #Messages( [bit] smallint not null, [message] varchar(64) not null ) insert into #Settings([type], [key], [value]) values ('string', 'alphabet', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='), ('integer', 'base', '64') insert into #Messages([bit], [message]) values (0, 'invalid_alphabet'), (1, 'invalid_base'), (2, 'invalid_alphabet_type'), (3, 'too_short_alphabet'), (4, 'repeated_characters_in_alphabet'), (5, 'too_long_alphabet'), (6, 'base_lower_than_2'), (7, 'base_greater_than_128'), (8, 'base_greater_than_alphabet') insert into dbo.Types([name]) select distinct [type] from #Settings where [type] not in ( select [name] from dbo.Types ) insert into dbo.Settings([type], [key], [value]) select types.id, settings.[key], settings.[value] from #Settings as settings inner join dbo.Types as types on types.name = settings.type where settings.[key] not in ( select [key] from dbo.Settings ) insert into dbo.Messages([bit], [message]) select [bit], [message] from #Messages where ([bit], [message]) not in ( select [bit], [message] from dbo.Messages ) if (select count(1) from dbo.Sets) = 0 begin end drop table #Settings end go if object_id(N'dbo.settings_get', N'FN') is not null drop function dbo.settings_get go create function dbo.settings_get( @key varchar(32), @default varchar(128) ) returns varchar(128) as begin return isnull(( select top 1 [value] from dbo.Settings where [key] = @key and date_out is null order by date_in desc ), @default) end go if object_id(N'dbo.settings_get_int', N'FN') is not null drop function dbo.settings_get_int go create function dbo.settings_get_int( @key varchar(32), @default integer ) returns integer as begin return convert(integer, dbo.settings_get(@key, @default)) end go if object_id(N'dbo.shift', N'FN') is not null drop function dbo.shift go create function dbo.shift( @value integer, @bits smallint ) returns integer as begin return (case when @bits is null or @value is null then 0 when @bits > 0 then @value * power(2, @bits) when @bits < 0 then @value / power(2, -@bits) else @value end) end go if object_id(N'dbo.unique', N'FN') is not null drop function dbo.unique go create function dbo.unique( @string varchar(max) ) returns varchar(128) as begin declare @i integer = 1 declare @l integer = datalength(@string) declare @unique varchar(128) = '' while @i <= @l begin declare @character char(1) = substring(@string, @i, 1) if charindex(@character, @unique) = 0 set @unique += @character set @i += 1 end return @unique end go if object_id(N'dbo.log2', N'FN') is not null drop function dbo.log2 go create function dbo.log2( @value float ) returns float as begin return log(@value) / log(2) end go if object_id(N'dbo.set_alphabet', N'P') is not null drop procedure dbo.set_alphabet go create procedure dbo.set_alphabet( @alphabet varchar(max), @base smallint, @id integer output, @error integer output ) begin set nocount on declare @original_length integer declare @power tinyint set @error = 0 if @alphabet is null set @alphabet = dbo.settings_get('alphabet', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') if @base is null set @base = dbo.settings_get_int('base', 64) set @original_length = datalength(@alphabet) set @alphabet = dbo.unique(@alphabet) if datalength(@alphabet) > 2 begin set @error = @error | dbo.shift(1, 3) set @alphabet = dbo.settings_get('alphabet', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') end if datalength(@alphabet) != original_length set @error = @error | dbo.shift(1, 4) if datalength(@alphabet) > 128 set @error = @error | dbo.shift(1, 5) set @error = @error | dbo.shift(1, case when @base < 2 then 6 when @base > 128 then 7 when @base >= datalength(@alphabet) then 8 else null end) if dbo.shift(error, -6) = 0 set @alphabet = substring(@alphabet, 1, @base) set @power = cast(dbo.log2(datalength(substring(@alphabet, 1, 128))) as integer) set @base = power(2, @power) insert into dbo.Sets(alphabet, base, power) values (substring(@alphabet, 1, @base), @base, @power) set @id = scope_identity() end go if object_id(N'dbo.change', N'P') is not null drop procedure dbo.change go create procedure dbo.change( @key varchar(32) ) begin set nocount on if (select top 1 0 from dbo.Sets where [key] = @key and in_use = 1) = 0 begin update dbo.Sets set in_use = 0 where in_use = 1 update dbo.Sets set in_use = 1, last_selection = getdate() where [key] = @key end end if object_id(N'dbo.get_alphabet', N'FN') is not null drop function dbo.get_alphabet go create function dbo.get_alphabet() returns varchar(128) as begin return (select top 1 alphabet from dbo.Sets where in_use = 1) end go if object_id(N'dbo.to_string', N'FN') is not null drop function dbo.to_string go create function dbo.to_string( @code integer ) returns varchar(512) as begin declare @hexas varchar(512) = '' declare @alphabet varchar(128) declare @base smallint select top 1 @alphabet = alphabet, @base = base from dbo.Sets where in_use = 1 while @code != 0 begin declare @module integer = @code % @base set @hexas = @hexas + substring(@alphabet, @module + 1, 1) set @code = @code / @base end return @hexas end go if object_id(N'dbo.to_integer', N'FN') is not null drop function dbo.to_integer go create function dbo.to_integer( @code varchar(512) ) returns integer as begin declare @integer integer = 0 declare @alphabet varchar(128) declare @base smallint declare @i integer = datalength(@code) select top 1 @alphabet = alphabet, @base = base from dbo.Sets where in_use = 1 while @i > 0 begin declare @value integer = charindex(substring(@code, @i, 1), @alphabet) if @value != 0 set @integer = @integer * @base + @value - 1 set @i = @i - 1 end return @integer end go if object_id(N'dbo.to_binary', N'FN') is not null drop function dbo.to_binary go create function dbo.to_binary( @integer integer ) returns varchar(32) as begin declare @binary varchar(32) = '' while @integer != 0 begin set @binary = convert(char(1), @integer % 2) + @binary set @integer = @integer / 2 end return @binary end go if object_id(N'dbo.to_string_binary', N'FN') is not null drop function dbo.to_string_binary go create function dbo.to_string_binary( @string varchar(512), @integer integer ) returns varchar(3584) as begin declare @binary varchar(3584) = '' declare @alphabet varchar(128) declare @base smallint declare @power tinyint select top 1 @alphabet = alphabet, @base = base, @power = power from dbo.Sets where in_use = 1 if @string is not null begin declare @i integer = datalength(@string) while @i > 0 begin declare @value integer = charindex(substring(@string, @i, 1), @alphabet) if @value != 0 set @binary = right('0000000' + dbo.to_binary(@value - 1), @power) + @binary set @i = @i - 1 end end else if @integer is not null begin set @binary = dbo.to_binary(@integer) while len(@binary) % @power != 0 set @binary = '0' + @binary end return @binary end go if object_id(N'dbo.get_bits', N'FN') is not null drop function dbo.get_bits go create function dbo.get_bits( @string varchar(512), @integer integer ) returns smallint as begin if @string is not null begin declare @alphabet varchar(128) declare @base smallint declare @power tinyint select top 1 @alphabet = alphabet, @base = base, @power = power from dbo.Sets where in_use = 1 return (case when datalength(@string) = 0 then 0 else (datalength(@string) - 1) * @power + ceiling(dbo.log2(charindex(substring(@string, datalength(@string), 1), @alphabet))) end) end if @integer is not null return ceiling(dbo.log2(@integer)) return 0 end go if object_id(N'dbo.get_from_bits', N'P') is not null drop procedure dbo.get_from_bits go create procedure dbo.get_from_bits( @string varchar(512), @integer integer, @from smallint output, @bits smallint output ) begin set nocount on if @from < 0 begin set @from = dbo.get_bits(@string, @integer) + @from if @from < 0 set @from = 0 end if @bits < 0 begin set @from = @from + @bits set @bits = -@bits if @from < 0 begin set @bits = @bits + @from set @from = 0 end end end go if object_id(N'dbo.clean', N'P') is not null drop procedure dbo.clean go create procedure dbo.clean( @string varchar(512) output, @integer integer output ) as begin set nocount on if @string is not null begin declare @character_0 char(1) select top 1 @character_0 = substring(alphabet, 1, 1) from dbo.Sets where in_use = 1 while datalength(@string) != 0 and right(@string, 1) = @character_0 set @string = left(@string, datalength(@string) - 1) if @string = '' set @string = @character_0 end end go if object_id(N'dbo.get_range', N'P') is not null drop procedure dbo.get_range go create procedure dbo.get_range( @string varchar(512) output, @integer integer output, @from smallint, @bits smallint ) begin set nocount on if @string is not null begin execute dbo.get_from_bits @string, @integer, @from output, @bits output if bits = 0 set bits = dbo.get_bits(@string, @integer) - @from if bits > 0 begin declare @alphabet varchar(128) declare @base smallint declare @power tinyint select top 1 @alphabet = alphabet, @base = base, @power = power from dbo.Sets where in_use = 1 if @from > 0 begin declare shift smallint = @from % @power declare mask smallint = ~-@base set @string = substring(@string, @from / @power + 1, datalength(@string)) if @shift != 0 and datalength(@string) > 0 begin declare l integer = datalength(@string) declare i integer = 1 while i < l begin set @string = ( left(@string, i - 1) + substring(@alphabet, (( dbo.shift(charindex(@alphabet, substring(@string, i, 1)), @shift) | dbo.shift(charindex(@alphabet, substring(@string, i + 1, 1)), @power - @shift) ) & @mask) + 1, 1) + right(@string, l - i) ) set i = i + 1 end end end if @bits > 0 begin declare @shift smallint = @bits % @power set @string = left(@string, ceiling((@from + @bits) / @power)) if @shift != 0 and datalength(@string) > 0 begin set @string = ( substring(@string, 1, datalength(@string) - 1) + substring(@alphabet, ( dbo.shift(charindex(@alphabet, right(@string, 1)), -@shift) & ~-power(2, @power - @shift) ) + 1, 1) ) end end execute dbo.clean @string output, @integer output end else if @integer is not null begin execute dbo.get_from_bits null, @integer, @from output, @bits output if @from > 0 set @code = dbo.shift(@code, @from) & (dbo.shift(1, 31 - @from) - 1) if @bits > 0 || @bits < 31 begin if @from + @bits > 31 set @bits = 31 - @from set @integer = @integer & (dbo.shift(1, @bits) - 1) end end end go