В plsql отсутствует нативная поддержка побитовых операций, кроме одной - bitand. При необходимости данную возможность можно реализовать самостоятельно. Ниже приведен пример реализации побитового OR и побитового XOR:
-- bit or
function bitor(x number, y number) return number
is
begin
return (x + y) - bitand(x, y);
end;
-- bit xor
function bitxor(x number, y number) return number
is
begin
return (x + y) - bitand(x, y) * 2;
end;
Для реализации операций побитовых сдвигов можно воспользоваться следующим подходом:
declare
-- convert binary to decimal
function bin2dec(binval in varchar2) return number
is
l_digits number;
l_curr_digit char(1);
l_curr_digit_dec number;
l_result number := 0;
begin
l_digits := length(binval);
for i in 1..l_digits loop
l_curr_digit := substr(binval, i, 1);
l_curr_digit_dec := to_number(l_curr_digit);
l_result := (l_result * 2) + l_curr_digit_dec;
end loop;
return l_result;
end;
-- convert decimal to binary
function dec2bin(p_num number) return varchar2
is
binval varchar2(64);
l_num number := p_num;
begin
while (l_num > 0) loop
binval := mod(l_num, 2) || binval;
l_num := trunc(l_num / 2);
end loop;
return binval;
end;
-- bitwise >> for binary
function bin_shift_right(p_bin in varchar2, p_shift in number default null) return varchar2
is
l_length number;
l_shift number;
begin
l_length := length(p_bin);
l_shift := nvl(p_shift, 1);
if (l_length <= 0) then
return null;
end if;
if (l_shift > l_length) then
l_shift := l_length;
end if;
return lpad(substr(p_bin, 1, l_length - l_shift), l_length, '0');
end;
-- bitwise >> for decimal
function shift_right(p_num in number, p_shift in number default null) return number
is
begin
if (trunc(p_num) <> p_num or p_num < 0) then
raise program_error;
end if;
return nvl(bin2dec(bin_shift_right(dec2bin(p_num), p_shift)), 0);
end;
begin
dbms_output.put_line(bin2dec('1000')); -- 8
dbms_output.put_line(shift_right(8, 1)); -- 4
dbms_output.put_line(dec2bin(shift_right(8, 1))); -- 100
end;
Ниже приведен пример использования побитовых операций для контроля возникающих в приложении ошибок:
declare
-- errors bit
ERROR_FIRST constant integer := 1; -- 0001
ERROR_SECOND constant integer := 2; -- 0010
ERROR_THIRD constant integer := 4; -- 0100
ERROR_FOURTH constant integer := 8; -- 1000
-- for capturing errors
l_errors number := 0;
-- bit or
function bitor(x number, y number) return number
is
begin
return (x + y) - bitand(x, y);
end;
-- bit xor
function bitxor(x number, y number) return number
is
begin
return (x + y) - bitand(x, y) * 2;
end;
-- set error bit
procedure set_error(p_errors in out number, p_error number)
is
begin
p_errors := bitor(p_errors, p_error);
end;
-- check if given error captured
function check_error(p_errors in number, p_error number) return boolean
is
begin
return bitand(p_errors, p_error) = p_error;
end;
-- print all captured errors
procedure print_errors(p_errors in number)
is
l_err varchar2(4000) := 'Catched errors:';
begin
if (check_error(p_errors, ERROR_FIRST)) then
l_err := l_err || ' ERROR_FIRST,';
end if;
if (check_error(p_errors, ERROR_SECOND)) then
l_err := l_err || ' ERROR_SECOND,';
end if;
if (check_error(p_errors, ERROR_THIRD)) then
l_err := l_err || ' ERROR_THIRD,';
end if;
if (check_error(p_errors, ERROR_FOURTH)) then
l_err := l_err || ' ERROR_FOURTH,';
end if;
dbms_output.put_line(l_err);
end;
begin
set_error(l_errors, ERROR_FIRST);
set_error(l_errors, ERROR_FOURTH);
print_errors(l_errors);
end;